diff --git a/CvGameCoreDLL/CvCity.cpp b/CvGameCoreDLL/CvCity.cpp
index 378f25e..44f4bc3 100644
--- a/CvGameCoreDLL/CvCity.cpp
+++ b/CvGameCoreDLL/CvCity.cpp
@@ -309,6 +309,35 @@ void CvCity::init(int iID, PlayerTypes eOwner, int iX, int iY, bool bBumpUnits,
GC.getGameINLINE().updatePlotGroups();
}
+ // AGDM addition, apply civic effects:
+ for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
+ {
+ for (int iJ = 0; iJ < NUM_YIELD_TYPES; ++iJ)
+ {
+ for (int iK = 0; iK < GC.getNumCivicOptionInfos(); iK++)
+ {
+ CivicTypes eCivic = GET_PLAYER(getOwnerINLINE()).getCivics((CivicOptionTypes)iK);
+ if (GC.getCivicInfo(eCivic).getBuildingYieldChanges(iI, iJ) != 0)
+ {
+ changeBuildingYieldChange((BuildingClassTypes)iI, (YieldTypes)iJ, (GC.getCivicInfo(eCivic)).getBuildingYieldChanges(iI, iJ));
+ }
+ }
+ }
+ for (iJ = 0; iJ < NUM_COMMERCE_TYPES; ++iJ)
+ {
+ for (int iK = 0; iK < GC.getNumCivicOptionInfos(); iK++)
+ {
+ CivicTypes eCivic = GET_PLAYER(getOwnerINLINE()).getCivics((CivicOptionTypes)iK);
+ if (GC.getCivicInfo(eCivic).getBuildingCommerceChanges(iI, iJ) != 0)
+ {
+ changeBuildingCommerceChange((BuildingClassTypes)iI, (CommerceTypes)iJ, (GC.getCivicInfo(eCivic)).getBuildingCommerceChanges(iI, iJ));
+ }
+ }
+ }
+ }
+
+ pPlot->updateYield(); // AGDM addition
+
AI_init();
}
@@ -1122,6 +1151,23 @@ void CvCity::updateVisibility()
void CvCity::createGreatPeople(UnitTypes eGreatPersonUnit, bool bIncrementThreshold, bool bIncrementExperience)
{
GET_PLAYER(getOwnerINLINE()).createGreatPeople(eGreatPersonUnit, bIncrementThreshold, bIncrementExperience, getX_INLINE(), getY_INLINE());
+ // AGDM addition: Add settled great people for PHI.
+ int iI, iJ;
+ int iExtraSettledGreatPeople = GC.getDefineINT("EXTRA_SETTLED_GREAT_PEOPLE_FROM_PHI");
+ if(iExtraSettledGreatPeople > 0 && bIncrementThreshold) {
+ for (iJ = 0; iJ < GC.getNumTraitInfos(); iJ++)
+ {
+ if(GET_PLAYER(getOwnerINLINE()).hasTrait((TraitTypes)iJ) && GC.getTraitInfo((TraitTypes)iJ).getGreatPeopleRateModifier() > 0) {
+ for (iI = 0; iI < GC.getNumSpecialistInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eGreatPersonUnit).getGreatPeoples(iI))
+ {
+ changeFreeSpecialistCount((SpecialistTypes)iI, iExtraSettledGreatPeople);
+ }
+ }
+ }
+ }
+ }
}
@@ -3695,12 +3741,31 @@ void CvCity::processBuilding(BuildingTypes eBuilding, int iChange, bool bObsolet
changeBaseYieldRate(((YieldTypes)iI), ((GC.getBuildingInfo(eBuilding).getYieldChange(iI) + getBuildingYieldChange((BuildingClassTypes)GC.getBuildingInfo(eBuilding).getBuildingClassType(), (YieldTypes)iI))* iChange));
changeYieldRateModifier(((YieldTypes)iI), (GC.getBuildingInfo(eBuilding).getYieldModifier(iI) * iChange));
changePowerYieldRateModifier(((YieldTypes)iI), (GC.getBuildingInfo(eBuilding).getPowerYieldModifier(iI) * iChange));
+ // AGDM addition: Add building yield modifiers and commerce modifiers from civics
+ for(iJ = 0; iJ < GC.getNumCivicOptionInfos(); iJ++)
+ {
+ CivicTypes eCivic = GET_PLAYER(getOwnerINLINE()).getCivics((CivicOptionTypes)iJ);
+ changeYieldRateModifier((YieldTypes)iI, GC.getCivicInfo(eCivic).getBuildingYieldModifiers(GC.getBuildingInfo(eBuilding).getBuildingClassType(), iI) * iChange);
+ }
}
for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
{
changeCommerceRateModifier(((CommerceTypes)iI), (GC.getBuildingInfo(eBuilding).getCommerceModifier(iI) * iChange));
changeCommerceHappinessPer(((CommerceTypes)iI), (GC.getBuildingInfo(eBuilding).getCommerceHappiness(iI) * iChange));
+ // AGDM addition: Add building yield modifiers and commerce modifiers from civics
+ for(iJ = 0; iJ < GC.getNumCivicOptionInfos(); iJ++)
+ {
+ CivicTypes eCivic = GET_PLAYER(getOwnerINLINE()).getCivics((CivicOptionTypes)iJ);
+ changeCommerceRateModifier((CommerceTypes)iI, GC.getCivicInfo(eCivic).getBuildingCommerceModifiers(GC.getBuildingInfo(eBuilding).getBuildingClassType(), iI) * iChange);
+ }
+ }
+ // AGDM addition: Get military production and free experience from civics
+ for(iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
+ {
+ CivicTypes eCivic = GET_PLAYER(getOwnerINLINE()).getCivics((CivicOptionTypes)iI);
+ changeMilitaryProductionModifier(GC.getCivicInfo(eCivic).getBuildingMilitaryProductionModifiers(GC.getBuildingInfo(eBuilding).getBuildingClassType()) * iChange);
+ changeFreeExperience(GC.getCivicInfo(eCivic).getBuildingFreeExperiences(GC.getBuildingInfo(eBuilding).getBuildingClassType()) * iChange);
}
for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
@@ -3712,6 +3777,13 @@ void CvCity::processBuilding(BuildingTypes eBuilding, int iChange, bool bObsolet
{
changeMaxSpecialistCount(((SpecialistTypes)iI), GC.getBuildingInfo(eBuilding).getSpecialistCount(iI) * iChange);
changeFreeSpecialistCount(((SpecialistTypes)iI), GC.getBuildingInfo(eBuilding).getFreeSpecialistCount(iI) * iChange);
+ // AGDM addition: Add free specialists from civics
+ for(iJ = 0; iJ < GC.getNumCivicOptionInfos(); iJ++)
+ {
+ CivicTypes eCivic = GET_PLAYER(getOwnerINLINE()).getCivics((CivicOptionTypes)iJ);
+ int iS = GC.getCivicInfo(eCivic).getBuildingFreeSpecialistCounts(GC.getBuildingInfo(eBuilding).getBuildingClassType(), iI);
+ changeFreeSpecialistCount((SpecialistTypes)iI, iS * iChange);
+ }
}
for (iI = 0; iI < GC.getNumImprovementInfos(); ++iI)
@@ -9565,7 +9637,17 @@ int CvCity::getMaxSpecialistCount(SpecialistTypes eIndex) const
{
FAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
FAssertMsg(eIndex < GC.getNumSpecialistInfos(), "eIndex expected to be < GC.getNumSpecialistInfos()");
- return m_paiMaxSpecialistCount[eIndex];
+
+ //Plako for RtRmod 20.7.2015
+ //If RtRSpecialistCount tied into a civic is > 0 add those to max specialist counts
+ int rtRExtraSpecialistCount = 0;
+ for (int iI = 0; iI < GC.getNumCivicInfos(); iI++) {
+ if (GET_PLAYER(getOwnerINLINE()).isCivic((CivicTypes)iI)) {
+ rtRExtraSpecialistCount += GC.getCivicInfo((CivicTypes)iI).getRtRExtraSpecialistCounts(eIndex);
+ }
+ }
+
+ return m_paiMaxSpecialistCount[eIndex]+rtRExtraSpecialistCount;
}
diff --git a/CvGameCoreDLL/CvDLLWidgetData.cpp b/CvGameCoreDLL/CvDLLWidgetData.cpp
index a13a7a1..6fa42b1 100644
--- a/CvGameCoreDLL/CvDLLWidgetData.cpp
+++ b/CvGameCoreDLL/CvDLLWidgetData.cpp
@@ -3581,6 +3581,15 @@ void CvDLLWidgetData::parseMaintenanceHelp(CvWidgetDataStruct &widgetDataStruct,
szBuffer.append(gDLL->getText("TXT_KEY_MISC_CORPORATION_MAINT_FLOAT", szMaint.GetCString()));
}
+ // AGDM addition: Inform about reduced mainenance due to trait introduced by T-hawk for RB balance mod. Works multiplicatively after discounts from courthouse/etc.
+ int iCityUpkeepModifier = GET_PLAYER(pHeadSelectedCity->getOwnerINLINE()).getCityUpkeepModifier();
+ if (iCityUpkeepModifier != 0)
+ {
+ CvWString szMaint = CvWString::format(L"%d%%", 0-iCityUpkeepModifier);
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_TRAITS_MAINT", szMaint.GetCString()));
+ }
+
szBuffer.append(SEPARATOR);
// swprintf(szTempBuffer, "\n%d%c Total Maintenance", pHeadSelectedCity->getMaintenance(), GC.getCommerceInfo(COMMERCE_GOLD).getChar());
diff --git a/CvGameCoreDLL/CvEnums.h b/CvGameCoreDLL/CvEnums.h
new file mode 100644
index 0000000..7214737
--- /dev/null
+++ b/CvGameCoreDLL/CvEnums.h
@@ -0,0 +1,2761 @@
+#pragma once
+
+#ifndef CVENUMS_h
+#define CVENUMS_h
+
+// enums.h
+
+#include "CvDefines.h"
+
+enum GameStateTypes // Exposed to Python
+{
+ GAMESTATE_ON,
+ GAMESTATE_OVER,
+ GAMESTATE_EXTENDED,
+};
+
+enum PopupStates // Exposed to Python
+{
+ POPUPSTATE_IMMEDIATE,
+ POPUPSTATE_QUEUED,
+ POPUPSTATE_MINIMIZED,
+};
+
+enum PopupEventTypes
+{
+ POPUPEVENT_NONE,
+ POPUPEVENT_PRODUCTION,
+ POPUPEVENT_TECHNOLOGY,
+ POPUPEVENT_RELIGION,
+ POPUPEVENT_WARNING,
+ POPUPEVENT_CIVIC,
+};
+
+enum CameraLookAtTypes // Exposed to Python
+{
+ CAMERALOOKAT_NORMAL,
+ CAMERALOOKAT_CITY_ZOOM_IN,
+ CAMERALOOKAT_BATTLE,
+ CAMERALOOKAT_BATTLE_ZOOM_IN,
+ CAMERALOOKAT_SHRINE_ZOOM_IN,
+ CAMERALOOKAT_IMMEDIATE,
+ CAMERALOOKAT_HOTSEAT,
+};
+
+enum CameraMovementSpeeds // Exposed to Python
+{
+ CAMERAMOVEMENTSPEED_NORMAL,
+ CAMERAMOVEMENTSPEED_SLOW,
+ CAMERAMOVEMENTSPEED_FAST,
+};
+
+enum CameraAnimationTypes
+{
+ NO_CAMERA_ANIMATION = -1,
+};
+
+enum ZoomLevelTypes // Exposed to Python
+{
+ ZOOM_UNKNOWN = 0x00000000,
+ ZOOM_DETAIL = 0x00000001,
+ ZOOM_NORMAL = 0x00000002,
+ ZOOM_GLOBEVIEW_TRANSITION = 0x00000004,
+ ZOOM_GLOBEVIEW = 0x00000008
+};
+
+enum DirectionTypes // Exposed to Python
+{
+ NO_DIRECTION = -1,
+
+ DIRECTION_NORTH,
+ DIRECTION_NORTHEAST,
+ DIRECTION_EAST,
+ DIRECTION_SOUTHEAST,
+ DIRECTION_SOUTH,
+ DIRECTION_SOUTHWEST,
+ DIRECTION_WEST,
+ DIRECTION_NORTHWEST,
+
+#ifdef _USRDLL
+ NUM_DIRECTION_TYPES,
+#endif
+
+ DIRECTION_NORTH_MASK = 1 << DIRECTION_NORTH,
+ DIRECTION_NORTHEAST_MASK = 1 << DIRECTION_NORTHEAST,
+ DIRECTION_EAST_MASK = 1 << DIRECTION_EAST,
+ DIRECTION_SOUTHEAST_MASK = 1 << DIRECTION_SOUTHEAST,
+ DIRECTION_SOUTH_MASK = 1 << DIRECTION_SOUTH,
+ DIRECTION_SOUTHWEST_MASK = 1 << DIRECTION_SOUTHWEST,
+ DIRECTION_WEST_MASK = 1 << DIRECTION_WEST,
+ DIRECTION_NORTHWEST_MASK = 1 << DIRECTION_NORTHWEST,
+};
+
+enum CardinalDirectionTypes // Exposed to Python
+{
+ NO_CARDINALDIRECTION = -1,
+
+ CARDINALDIRECTION_NORTH,
+ CARDINALDIRECTION_EAST,
+ CARDINALDIRECTION_SOUTH,
+ CARDINALDIRECTION_WEST,
+
+#ifdef _USRDLL
+ NUM_CARDINALDIRECTION_TYPES
+#endif
+};
+
+enum RotationTypes
+{
+ ROTATE_NONE = 0,
+ ROTATE_90CW,
+ ROTATE_180CW,
+ ROTATE_270CW,
+ NUM_ROTATION_TYPES,
+
+ ROTATE_NONE_MASK = 1 << ROTATE_NONE,
+ ROTATE_90CW_MASK = 1 << ROTATE_90CW,
+ ROTATE_180CW_MASK = 1 << ROTATE_180CW,
+ ROTATE_270CW_MASK = 1 << ROTATE_270CW,
+};
+
+// camera wrap helper
+enum WrapDirection
+{
+ WRAP_SAVE,
+ WRAP_NONE = WRAP_SAVE,
+ WRAP_RESTORE,
+ WRAP_LEFT,
+ WRAP_RIGHT,
+ WRAP_UP,
+ WRAP_DOWN,
+
+#ifdef _USRDLL
+ NUM_WRAP_DIRECTIONS,
+#endif
+
+ WRAP_LEFT_MASK = 1 << WRAP_LEFT,
+ WRAP_RIGHT_MASK = 1 << WRAP_RIGHT,
+ WRAP_UP_MASK = 1 << WRAP_UP,
+ WRAP_DOWN_MASK = 1 << WRAP_DOWN,
+};
+
+enum ColorTypes // Exposed to Python
+{
+ NO_COLOR = -1,
+};
+
+enum PlayerColorTypes // Exposed to Python
+{
+ NO_PLAYERCOLOR = -1,
+};
+
+//Warning: these values correspond to locations in the plot texture [JW]
+enum PlotStyles // Exposed to Python
+{
+ PLOT_STYLE_NONE = -1,
+
+ //first row
+ PLOT_STYLE_NUMPAD_1 = 0,
+ PLOT_STYLE_NUMPAD_2,
+ PLOT_STYLE_NUMPAD_3,
+ PLOT_STYLE_NUMPAD_4,
+ PLOT_STYLE_NUMPAD_6,
+ PLOT_STYLE_NUMPAD_7,
+ PLOT_STYLE_NUMPAD_8,
+ PLOT_STYLE_NUMPAD_9,
+
+ //second row
+ PLOT_STYLE_NUMPAD_1_ANGLED = 8,
+ PLOT_STYLE_NUMPAD_2_ANGLED,
+ PLOT_STYLE_NUMPAD_3_ANGLED,
+ PLOT_STYLE_NUMPAD_4_ANGLED,
+ PLOT_STYLE_NUMPAD_6_ANGLED,
+ PLOT_STYLE_NUMPAD_7_ANGLED,
+ PLOT_STYLE_NUMPAD_8_ANGLED,
+ PLOT_STYLE_NUMPAD_9_ANGLED,
+
+ //third row
+ PLOT_STYLE_BOX_FILL = 16,
+ PLOT_STYLE_BOX_OUTLINE,
+ PLOT_STYLE_RIVER_SOUTH,
+ PLOT_STYLE_RIVER_EAST,
+ PLOT_STYLE_SIDE_ARROWS,
+ PLOT_STYLE_CIRCLE,
+ PLOT_STYLE_TARGET,
+ PLOT_STYLE_DOT_TARGET,
+
+ //fourth row
+ PLOT_STYLE_WAVES = 24,
+ PLOT_STYLE_DOTS,
+ PLOT_STYLE_CIRCLES,
+};
+
+//Warning: these values are used as an index into a fixed array
+enum PlotLandscapeLayers // Exposed to Python
+{
+ PLOT_LANDSCAPE_LAYER_ALL = -1,
+ PLOT_LANDSCAPE_LAYER_BASE = 0,
+ PLOT_LANDSCAPE_LAYER_RECOMMENDED_PLOTS = 1,
+ PLOT_LANDSCAPE_LAYER_WORLD_BUILDER = 2,
+ PLOT_LANDSCAPE_LAYER_NUMPAD_HELP = 2,
+ PLOT_LANDSCAPE_LAYER_REVEALED_PLOTS = 1,
+};
+
+enum AreaBorderLayers
+{
+ AREA_BORDER_LAYER_REVEALED_PLOTS,
+ AREA_BORDER_LAYER_WORLD_BUILDER,
+ AREA_BORDER_LAYER_FOUNDING_BORDER,
+ AREA_BORDER_LAYER_CITY_RADIUS,
+ AREA_BORDER_LAYER_RANGED,
+ AREA_BORDER_LAYER_HIGHLIGHT_PLOT,
+ AREA_BORDER_LAYER_BLOCKADING,
+ AREA_BORDER_LAYER_BLOCKADED,
+ NUM_AREA_BORDER_LAYERS
+};
+
+enum EffectTypes
+{
+ NO_EFFECT = -1,
+};
+
+enum AttachableTypes
+{
+ NO_ATTACHABLE = -1,
+};
+
+enum InterfaceModeTypes // Exposed to Python
+{
+ NO_INTERFACEMODE = -1,
+
+ INTERFACEMODE_SELECTION,
+ INTERFACEMODE_PING,
+ INTERFACEMODE_SIGN,
+ INTERFACEMODE_GRIP,
+ INTERFACEMODE_GLOBELAYER_INPUT,
+ INTERFACEMODE_GO_TO,
+ INTERFACEMODE_GO_TO_TYPE,
+ INTERFACEMODE_GO_TO_ALL,
+ INTERFACEMODE_ROUTE_TO,
+ INTERFACEMODE_AIRLIFT,
+ INTERFACEMODE_NUKE,
+ INTERFACEMODE_RECON,
+ INTERFACEMODE_PARADROP,
+ INTERFACEMODE_AIRBOMB,
+ INTERFACEMODE_RANGE_ATTACK,
+ INTERFACEMODE_AIRSTRIKE,
+ INTERFACEMODE_REBASE,
+ INTERFACEMODE_PYTHON_PICK_PLOT,
+ INTERFACEMODE_SAVE_PLOT_NIFS,
+
+#ifdef _USRDLL
+ NUM_INTERFACEMODE_TYPES
+#endif
+};
+
+enum InterfaceMessageTypes // Exposed to Python
+{
+ NO_MESSAGE_TYPE = -1,
+
+ MESSAGE_TYPE_INFO,
+ MESSAGE_TYPE_DISPLAY_ONLY,
+ MESSAGE_TYPE_MAJOR_EVENT,
+ MESSAGE_TYPE_MINOR_EVENT,
+ MESSAGE_TYPE_CHAT,
+ MESSAGE_TYPE_COMBAT_MESSAGE,
+ MESSAGE_TYPE_QUEST,
+
+#ifdef _USRDLL
+ NUM_INTERFACE_MESSAGE_TYPES
+#endif
+};
+
+enum FlyoutTypes
+{
+ NO_FLYOUT = -1,
+
+ FLYOUT_HURRY,
+ FLYOUT_CONSCRIPT,
+ FLYOUT_TRAIN,
+ FLYOUT_CONSTRUCT,
+ FLYOUT_CREATE,
+ FLYOUT_MAINTAIN,
+ FLYOUT_MOVE_TO,
+ FLYOUT_SELECT_UNIT,
+ FLYOUT_SELECT_ALL,
+ FLYOUT_WAKE_ALL,
+ FLYOUR_FORTIFY_ALL,
+ FLYOUR_SLEEP_ALL,
+};
+
+enum MinimapModeTypes // Exposed to Python
+{
+ NO_MINIMAPMODE = -1,
+
+ MINIMAPMODE_TERRITORY,
+ MINIMAPMODE_TERRAIN,
+ MINIMAPMODE_REPLAY,
+ MINIMAPMODE_MILITARY,
+
+#ifdef _USRDLL
+ NUM_MINIMAPMODE_TYPES
+#endif
+};
+
+enum EngineDirtyBits // Exposed to Python
+{
+ GlobeTexture_DIRTY_BIT,
+ GlobePartialTexture_DIRTY_BIT,
+ MinimapTexture_DIRTY_BIT,
+ CultureBorders_DIRTY_BIT,
+
+#ifdef _USRDLL
+ NUM_ENGINE_DIRTY_BITS
+#endif
+};
+
+enum InterfaceDirtyBits // Exposed to Python
+{
+ SelectionCamera_DIRTY_BIT,
+ Fog_DIRTY_BIT,
+ GlobeLayer_DIRTY_BIT,
+ GlobeInfo_DIRTY_BIT,
+ Waypoints_DIRTY_BIT,
+ PercentButtons_DIRTY_BIT,
+ MiscButtons_DIRTY_BIT,
+ PlotListButtons_DIRTY_BIT,
+ SelectionButtons_DIRTY_BIT,
+ CitizenButtons_DIRTY_BIT,
+ ResearchButtons_DIRTY_BIT,
+ Event_DIRTY_BIT,
+ Center_DIRTY_BIT,
+ GameData_DIRTY_BIT,
+ Score_DIRTY_BIT,
+ TurnTimer_DIRTY_BIT,
+ Help_DIRTY_BIT,
+ MinimapSection_DIRTY_BIT,
+ SelectionSound_DIRTY_BIT,
+ Cursor_DIRTY_BIT,
+ CityInfo_DIRTY_BIT,
+ UnitInfo_DIRTY_BIT,
+ Popup_DIRTY_BIT,
+ CityScreen_DIRTY_BIT,
+ InfoPane_DIRTY_BIT,
+ Flag_DIRTY_BIT,
+ HighlightPlot_DIRTY_BIT,
+ ColoredPlots_DIRTY_BIT,
+ BlockadedPlots_DIRTY_BIT,
+ Financial_Screen_DIRTY_BIT,
+ Foreign_Screen_DIRTY_BIT,
+ Soundtrack_DIRTY_BIT,
+ Domestic_Advisor_DIRTY_BIT,
+ Espionage_Advisor_DIRTY_BIT,
+ Advanced_Start_DIRTY_BIT,
+
+#ifdef _USRDLL
+ NUM_INTERFACE_DIRTY_BITS
+#endif
+};
+
+enum CityTabTypes // Exposed to Python
+{
+ NO_CITYTAB = -1,
+
+ CITYTAB_UNITS,
+ CITYTAB_BUILDINGS,
+ CITYTAB_WONDERS,
+
+#ifdef _USRDLL
+ NUM_CITYTAB_TYPES
+#endif
+};
+
+enum WidgetTypes // Exposed to Python
+{
+ WIDGET_PLOT_LIST,
+ WIDGET_PLOT_LIST_SHIFT,
+ WIDGET_CITY_SCROLL,
+ WIDGET_LIBERATE_CITY,
+ WIDGET_CITY_NAME,
+ WIDGET_UNIT_NAME,
+ WIDGET_CREATE_GROUP,
+ WIDGET_DELETE_GROUP,
+ WIDGET_TRAIN,
+ WIDGET_CONSTRUCT,
+ WIDGET_CREATE,
+ WIDGET_MAINTAIN,
+ WIDGET_HURRY,
+ WIDGET_MENU_ICON,
+ WIDGET_CONSCRIPT,
+ WIDGET_ACTION,
+ WIDGET_DISABLED_CITIZEN,
+ WIDGET_CITIZEN,
+ WIDGET_FREE_CITIZEN,
+ WIDGET_ANGRY_CITIZEN,
+ WIDGET_CHANGE_SPECIALIST,
+ WIDGET_RESEARCH,
+ WIDGET_TECH_TREE,
+ WIDGET_CHANGE_PERCENT,
+ WIDGET_CITY_TAB,
+ WIDGET_CONTACT_CIV,
+ WIDGET_SCORE_BREAKDOWN,
+ WIDGET_ZOOM_CITY,
+ WIDGET_END_TURN,
+ WIDGET_LAUNCH_VICTORY,
+ WIDGET_CONVERT,
+ WIDGET_AUTOMATE_CITIZENS,
+ WIDGET_AUTOMATE_PRODUCTION,
+ WIDGET_EMPHASIZE,
+ WIDGET_DIPLOMACY_RESPONSE,
+ WIDGET_GENERAL,
+ WIDGET_FILE_LISTBOX,
+ WIDGET_FILE_EDITBOX,
+ WIDGET_WB_UNITNAME_EDITBOX,
+ WIDGET_WB_CITYNAME_EDITBOX,
+ WIDGET_WB_SAVE_BUTTON,
+ WIDGET_WB_LOAD_BUTTON,
+ WIDGET_WB_ALL_PLOTS_BUTTON,
+ WIDGET_WB_LANDMARK_BUTTON,
+ WIDGET_WB_ERASE_BUTTON,
+ WIDGET_WB_EXIT_BUTTON,
+ WIDGET_WB_UNIT_EDIT_BUTTON,
+ WIDGET_WB_CITY_EDIT_BUTTON,
+ WIDGET_WB_NORMAL_PLAYER_TAB_MODE_BUTTON,
+ WIDGET_WB_NORMAL_MAP_TAB_MODE_BUTTON,
+ WIDGET_WB_REVEAL_TAB_MODE_BUTTON,
+ WIDGET_WB_DIPLOMACY_MODE_BUTTON,
+ WIDGET_WB_REVEAL_ALL_BUTTON,
+ WIDGET_WB_UNREVEAL_ALL_BUTTON,
+ WIDGET_WB_REGENERATE_MAP,
+ WIDGET_TRADE_ITEM,
+ WIDGET_UNIT_MODEL,
+ WIDGET_FLAG,
+ WIDGET_POPUP_QUEUE,
+
+ // This is meant for python buttons, it will call python functions for display and execution
+ WIDGET_PYTHON,
+
+ // This button type is reserved for widgets meant to be displayed only. This is meant for general interface text and such...
+ WIDGET_HELP_MAINTENANCE,
+ WIDGET_HELP_RELIGION,
+ WIDGET_HELP_RELIGION_CITY,
+ WIDGET_HELP_CORPORATION_CITY,
+ WIDGET_HELP_NATIONALITY,
+ WIDGET_HELP_DEFENSE,
+ WIDGET_HELP_HEALTH,
+ WIDGET_HELP_HAPPINESS,
+ WIDGET_HELP_POPULATION,
+ WIDGET_HELP_PRODUCTION,
+ WIDGET_HELP_CULTURE,
+ WIDGET_HELP_GREAT_PEOPLE,
+ WIDGET_HELP_GREAT_GENERAL,
+ WIDGET_HELP_SELECTED,
+ WIDGET_HELP_BUILDING,
+ WIDGET_HELP_TRADE_ROUTE_CITY,
+ WIDGET_HELP_ESPIONAGE_COST,
+ WIDGET_HELP_TECH_ENTRY,
+ WIDGET_HELP_TECH_PREPREQ,
+ WIDGET_HELP_OBSOLETE,
+ WIDGET_HELP_OBSOLETE_BONUS,
+ WIDGET_HELP_OBSOLETE_SPECIAL,
+ WIDGET_HELP_MOVE_BONUS,
+ WIDGET_HELP_FREE_UNIT,
+ WIDGET_HELP_FEATURE_PRODUCTION,
+ WIDGET_HELP_WORKER_RATE,
+ WIDGET_HELP_TRADE_ROUTES,
+ WIDGET_HELP_HEALTH_RATE,
+ WIDGET_HELP_HAPPINESS_RATE,
+ WIDGET_HELP_FREE_TECH,
+ WIDGET_HELP_LOS_BONUS,
+ WIDGET_HELP_MAP_CENTER,
+ WIDGET_HELP_MAP_REVEAL,
+ WIDGET_HELP_MAP_TRADE,
+ WIDGET_HELP_TECH_TRADE,
+ WIDGET_HELP_GOLD_TRADE,
+ WIDGET_HELP_OPEN_BORDERS,
+ WIDGET_HELP_DEFENSIVE_PACT,
+ WIDGET_HELP_PERMANENT_ALLIANCE,
+ WIDGET_HELP_VASSAL_STATE,
+ WIDGET_HELP_BUILD_BRIDGE,
+ WIDGET_HELP_IRRIGATION,
+ WIDGET_HELP_IGNORE_IRRIGATION,
+ WIDGET_HELP_WATER_WORK,
+ WIDGET_HELP_IMPROVEMENT,
+ WIDGET_HELP_DOMAIN_EXTRA_MOVES,
+ WIDGET_HELP_ADJUST,
+ WIDGET_HELP_TERRAIN_TRADE,
+ WIDGET_HELP_SPECIAL_BUILDING,
+ WIDGET_HELP_YIELD_CHANGE,
+ WIDGET_HELP_BONUS_REVEAL,
+ WIDGET_HELP_CIVIC_REVEAL,
+ WIDGET_HELP_PROCESS_INFO,
+ WIDGET_HELP_FOUND_RELIGION,
+ WIDGET_HELP_FOUND_CORPORATION,
+ WIDGET_HELP_FINANCE_NUM_UNITS,
+ WIDGET_HELP_FINANCE_UNIT_COST,
+ WIDGET_HELP_FINANCE_AWAY_SUPPLY,
+ WIDGET_HELP_FINANCE_CITY_MAINT,
+ WIDGET_HELP_FINANCE_CIVIC_UPKEEP,
+ WIDGET_HELP_FINANCE_FOREIGN_INCOME,
+ WIDGET_HELP_FINANCE_INFLATED_COSTS,
+ WIDGET_HELP_FINANCE_GROSS_INCOME,
+ WIDGET_HELP_FINANCE_NET_GOLD,
+ WIDGET_HELP_FINANCE_GOLD_RESERVE,
+ WIDGET_HELP_PROMOTION,
+
+ WIDGET_CHOOSE_EVENT,
+ WIDGET_PEDIA_JUMP_TO_TECH,
+ WIDGET_PEDIA_JUMP_TO_UNIT,
+ WIDGET_PEDIA_JUMP_TO_BUILDING,
+ WIDGET_PEDIA_JUMP_TO_REQUIRED_TECH,
+ WIDGET_PEDIA_JUMP_TO_DERIVED_TECH,
+ WIDGET_PEDIA_BACK,
+ WIDGET_PEDIA_FORWARD,
+ WIDGET_PEDIA_JUMP_TO_BONUS,
+ WIDGET_PEDIA_MAIN,
+ WIDGET_PEDIA_JUMP_TO_PROMOTION,
+ WIDGET_PEDIA_JUMP_TO_UNIT_COMBAT,
+ WIDGET_PEDIA_JUMP_TO_IMPROVEMENT,
+ WIDGET_PEDIA_JUMP_TO_CIVIC,
+ WIDGET_PEDIA_JUMP_TO_CIV,
+ WIDGET_PEDIA_JUMP_TO_LEADER,
+ WIDGET_PEDIA_JUMP_TO_SPECIALIST,
+ WIDGET_PEDIA_JUMP_TO_PROJECT,
+ WIDGET_PEDIA_JUMP_TO_TERRAIN,
+ WIDGET_PEDIA_JUMP_TO_FEATURE,
+ WIDGET_TURN_EVENT,
+ WIDGET_FOREIGN_ADVISOR,
+ WIDGET_REVOLUTION,
+ WIDGET_PEDIA_DESCRIPTION,
+ WIDGET_PEDIA_DESCRIPTION_NO_HELP,
+ WIDGET_DEAL_KILL,
+ WIDGET_MINIMAP_HIGHLIGHT,
+ WIDGET_PRODUCTION_MOD_HELP,
+ WIDGET_LEADERHEAD,
+ WIDGET_LEADER_LINE,
+ WIDGET_COMMERCE_MOD_HELP,
+ WIDGET_CLOSE_SCREEN,
+ WIDGET_PEDIA_JUMP_TO_RELIGION,
+ WIDGET_PEDIA_JUMP_TO_CORPORATION,
+ WIDGET_GLOBELAYER,
+ WIDGET_GLOBELAYER_OPTION,
+ WIDGET_GLOBELAYER_TOGGLE,
+
+#ifdef _USRDLL
+ NUM_WIDGET_TYPES
+#endif
+};
+
+enum ButtonPopupTypes // Exposed to Python
+{
+ BUTTONPOPUP_TEXT,
+ BUTTONPOPUP_MAIN_MENU,
+ BUTTONPOPUP_CONFIRM_MENU,
+ BUTTONPOPUP_DECLAREWARMOVE,
+ BUTTONPOPUP_CONFIRMCOMMAND,
+ BUTTONPOPUP_LOADUNIT,
+ BUTTONPOPUP_LEADUNIT,
+ BUTTONPOPUP_DOESPIONAGE,
+ BUTTONPOPUP_DOESPIONAGE_TARGET,
+ BUTTONPOPUP_CHOOSETECH,
+ BUTTONPOPUP_RAZECITY,
+ BUTTONPOPUP_DISBANDCITY,
+ BUTTONPOPUP_CHOOSEPRODUCTION,
+ BUTTONPOPUP_CHANGECIVIC,
+ BUTTONPOPUP_CHANGERELIGION,
+ BUTTONPOPUP_CHOOSEELECTION,
+ BUTTONPOPUP_DIPLOVOTE,
+ BUTTONPOPUP_ALARM,
+ BUTTONPOPUP_DEAL_CANCELED,
+ BUTTONPOPUP_PYTHON,
+ BUTTONPOPUP_PYTHON_SCREEN,
+ BUTTONPOPUP_DETAILS,
+ BUTTONPOPUP_ADMIN,
+ BUTTONPOPUP_ADMIN_PASSWORD,
+ BUTTONPOPUP_EXTENDED_GAME,
+ BUTTONPOPUP_DIPLOMACY,
+ BUTTONPOPUP_ADDBUDDY,
+ BUTTONPOPUP_FORCED_DISCONNECT,
+ BUTTONPOPUP_PITBOSS_DISCONNECT,
+ BUTTONPOPUP_KICKED,
+ BUTTONPOPUP_VASSAL_DEMAND_TRIBUTE,
+ BUTTONPOPUP_VASSAL_GRANT_TRIBUTE,
+ BUTTONPOPUP_EVENT,
+ BUTTONPOPUP_FREE_COLONY,
+ BUTTONPOPUP_LAUNCH,
+ BUTTONPOPUP_FOUND_RELIGION,
+
+#ifdef _USRDLL
+ NUM_BUTTONPOPUP_TYPES
+#endif
+};
+
+enum ClimateTypes // Exposed to Python
+{
+ NO_CLIMATE = -1,
+};
+
+enum SeaLevelTypes // Exposed to Python
+{
+ NO_SEALEVEL = -1,
+};
+
+enum CustomMapOptionTypes // Exposed to Python
+{
+ NO_CUSTOM_MAPOPTION = -1,
+};
+
+enum WorldSizeTypes // Exposed to Python
+{
+ NO_WORLDSIZE = -1,
+
+ WORLDSIZE_DUEL,
+ WORLDSIZE_TINY,
+ WORLDSIZE_SMALL,
+ WORLDSIZE_STANDARD,
+ WORLDSIZE_LARGE,
+ WORLDSIZE_HUGE,
+
+#ifdef _USRDLL
+ NUM_WORLDSIZE_TYPES
+#endif
+};
+
+// This is our current relationship with each
+// one of our connected network peers
+enum InitStates
+{
+ INIT_INACTIVE,
+ INIT_CONNECTED,
+ INIT_SENT_READY,
+ INIT_READY,
+ INIT_ASSIGNED_ID,
+ INIT_SENT_ID,
+ INIT_PEER,
+ INIT_FILE_TRANSFER,
+ INIT_TRANSFER_COMPLETE,
+ INIT_AUTHORIZED,
+ INIT_MAP_CONFIRMED,
+ INIT_GAME_STARTED,
+};
+
+enum TerrainTypes // Exposed to Python
+{
+ NO_TERRAIN = -1,
+};
+
+enum PlotTypes // Exposed to Python
+{
+ NO_PLOT = -1,
+
+ PLOT_PEAK,
+ PLOT_HILLS,
+ PLOT_LAND,
+ PLOT_OCEAN,
+
+#ifdef _USRDLL
+ NUM_PLOT_TYPES
+#endif
+};
+
+enum YieldTypes // Exposed to Python
+{
+ NO_YIELD = -1,
+
+ YIELD_FOOD,
+ YIELD_PRODUCTION,
+ YIELD_COMMERCE,
+
+#ifdef _USRDLL
+ NUM_YIELD_TYPES
+#endif
+};
+
+enum CommerceTypes // Exposed to Python
+{
+ NO_COMMERCE = -1,
+
+ COMMERCE_GOLD,
+ COMMERCE_RESEARCH,
+ COMMERCE_CULTURE,
+ COMMERCE_ESPIONAGE,
+
+#ifdef _USRDLL
+ NUM_COMMERCE_TYPES
+#endif
+};
+
+enum AdvisorTypes // Exposed to Python
+{
+ NO_ADVISOR = -1
+};
+
+enum FlavorTypes // Exposed to Python
+{
+ NO_FLAVOR = -1
+};
+
+enum EmphasizeTypes // Exposed to Python
+{
+ NO_EMPHASIZE = -1,
+};
+
+enum GameOptionTypes // Exposed to Python
+{
+ NO_GAMEOPTION = -1,
+
+ GAMEOPTION_ADVANCED_START,
+ GAMEOPTION_NO_CITY_RAZING,
+ GAMEOPTION_NO_CITY_FLIPPING,
+ GAMEOPTION_FLIPPING_AFTER_CONQUEST,
+ GAMEOPTION_NO_BARBARIANS,
+ GAMEOPTION_RAGING_BARBARIANS,
+ GAMEOPTION_AGGRESSIVE_AI,
+ GAMEOPTION_LEAD_ANY_CIV,
+ GAMEOPTION_RANDOM_PERSONALITIES,
+ GAMEOPTION_PICK_RELIGION,
+ GAMEOPTION_NO_TECH_TRADING,
+ GAMEOPTION_NO_TECH_BROKERING,
+ GAMEOPTION_PERMANENT_ALLIANCES,
+ GAMEOPTION_ALWAYS_WAR,
+ GAMEOPTION_ALWAYS_PEACE,
+ GAMEOPTION_ONE_CITY_CHALLENGE,
+ GAMEOPTION_NO_CHANGING_WAR_PEACE,
+ GAMEOPTION_NEW_RANDOM_SEED,
+ GAMEOPTION_LOCK_MODS,
+ GAMEOPTION_COMPLETE_KILLS,
+ GAMEOPTION_NO_VASSAL_STATES,
+ GAMEOPTION_NO_GOODY_HUTS,
+ GAMEOPTION_NO_EVENTS,
+ GAMEOPTION_NO_ESPIONAGE,
+//Plako for RtR mod 11.8.2015
+ GAMEOPTION_NO_CITY_TRADING,
+
+
+#ifdef _USRDLL
+ NUM_GAMEOPTION_TYPES
+#endif
+};
+
+enum MultiplayerOptionTypes // Exposed to Python
+{
+ NO_MPOPTION = -1,
+
+ MPOPTION_SIMULTANEOUS_TURNS,
+ MPOPTION_TAKEOVER_AI,
+ MPOPTION_SHUFFLE_TEAMS,
+ MPOPTION_ANONYMOUS,
+ MPOPTION_TURN_TIMER,
+
+#ifdef _USRDLL
+ NUM_MPOPTION_TYPES
+#endif
+};
+
+enum SpecialOptionTypes // Exposed to Python
+{
+ NO_SPECIALOPTION = -1,
+
+ SPECIALOPTION_REPORT_STATS,
+
+#ifdef _USRDLL
+ NUM_SPECIALOPTION_TYPES
+#endif
+};
+
+enum PlayerOptionTypes // Exposed to Python
+{
+ NO_PLAYEROPTION = -1,
+
+ PLAYEROPTION_ADVISOR_POPUPS,
+ PLAYEROPTION_ADVISOR_HELP,
+ PLAYEROPTION_WAIT_END_TURN,
+ PLAYEROPTION_MINIMIZE_POP_UPS,
+ PLAYEROPTION_SHOW_FRIENDLY_MOVES,
+ PLAYEROPTION_SHOW_ENEMY_MOVES,
+ PLAYEROPTION_QUICK_MOVES,
+ PLAYEROPTION_QUICK_ATTACK,
+ PLAYEROPTION_QUICK_DEFENSE,
+ PLAYEROPTION_STACK_ATTACK,
+ PLAYEROPTION_AUTO_PROMOTION,
+ PLAYEROPTION_START_AUTOMATED,
+ PLAYEROPTION_SAFE_AUTOMATION,
+ PLAYEROPTION_NUMPAD_HELP,
+ PLAYEROPTION_NO_UNIT_CYCLING,
+ PLAYEROPTION_NO_UNIT_RECOMMENDATIONS,
+ PLAYEROPTION_RIGHT_CLICK_MENU,
+ PLAYEROPTION_LEAVE_FORESTS,
+ PLAYEROPTION_MISSIONARIES_AUTOMATED,
+ PLAYEROPTION_MODDER_1,
+ PLAYEROPTION_MODDER_2,
+ PLAYEROPTION_MODDER_3,
+
+#ifdef _USRDLL
+ NUM_PLAYEROPTION_TYPES
+#endif
+};
+
+enum GraphicOptionTypes // Exposed to Python
+{
+ NO_GRAPHICOPTION = -1,
+
+ GRAPHICOPTION_SINGLE_UNIT_GRAPHICS,
+ GRAPHICOPTION_HEALTH_BARS,
+ GRAPHICOPTION_CITY_DETAIL,
+ GRAPHICOPTION_NO_COMBAT_ZOOM,
+ GRAPHICOPTION_NO_ENEMY_GLOW,
+ GRAPHICOPTION_FROZEN_ANIMATIONS,
+ GRAPHICOPTION_EFFECTS_DISABLED,
+ GRAPHICOPTION_GLOBE_VIEW_BUILDINGS_DISABLED,
+ GRAPHICOPTION_FULLSCREEN,
+ GRAPHICOPTION_LOWRES_TEXTURES,
+ GRAPHICOPTION_HIRES_TERRAIN,
+ GRAPHICOPTION_NO_MOVIES,
+ GRAPHICOPTION_CITY_RADIUS,
+
+#ifdef _USRDLL
+ NUM_GRAPHICOPTION_TYPES
+#endif
+};
+
+enum ForceControlTypes // Exposed to Python
+{
+ NO_FORCECONTROL = -1,
+
+ FORCECONTROL_SPEED,
+ FORCECONTROL_HANDICAP,
+ FORCECONTROL_OPTIONS,
+ FORCECONTROL_VICTORIES,
+ FORCECONTROL_MAX_TURNS,
+ FORCECONTROL_MAX_CITY_ELIMINATION,
+ FORCECONTROL_ADVANCED_START,
+
+#ifdef _USRDLL
+ NUM_FORCECONTROL_TYPES
+#endif
+};
+
+enum TileArtTypes
+{
+ TILE_ART_TYPE_NONE = -1,
+ TILE_ART_TYPE_TREES,
+ TILE_ART_TYPE_HALF_TILING,
+ TILE_ART_TYPE_PLOT_TILING,
+ NUM_TILE_ART_TYPES
+};
+
+enum LightTypes
+{
+ LIGHT_TYPE_NONE = -1,
+ LIGHT_TYPE_SUN,
+ LIGHT_TYPE_TERRAIN,
+ LIGHT_TYPE_UNIT,
+ NUM_LIGHT_TYPES
+};
+
+enum VictoryTypes // Exposed to Python
+{
+ NO_VICTORY = -1,
+};
+
+enum FeatureTypes // Exposed to Python
+{
+ NO_FEATURE = -1,
+};
+
+enum BonusTypes // Exposed to Python
+{
+ NO_BONUS = -1,
+};
+
+enum BonusClassTypes // Exposed to Python
+{
+ NO_BONUSCLASS = -1,
+};
+
+enum ImprovementTypes // Exposed to Python
+{
+ NO_IMPROVEMENT = -1,
+};
+
+enum RouteTypes // Exposed to Python
+{
+ NO_ROUTE = -1,
+};
+
+enum RiverTypes // Exposed to Python
+{
+ NO_RIVER = -1,
+};
+
+enum GoodyTypes // Exposed to Python
+{
+ NO_GOODY = -1,
+};
+
+enum BuildTypes // Exposed to Python
+{
+ NO_BUILD = -1,
+};
+
+enum SymbolTypes // Exposed to Python
+{
+ NO_SYMBOL = -1,
+};
+
+enum FontSymbols // Exposed to Python
+{
+ // 'OTHER' symbols
+ HAPPY_CHAR = 0,
+ UNHAPPY_CHAR,
+ HEALTHY_CHAR,
+ UNHEALTHY_CHAR,
+ BULLET_CHAR,
+ STRENGTH_CHAR,
+ MOVES_CHAR,
+ RELIGION_CHAR,
+ STAR_CHAR,
+ SILVER_STAR_CHAR,
+ TRADE_CHAR,
+ DEFENSE_CHAR,
+ GREAT_PEOPLE_CHAR,
+ BAD_GOLD_CHAR,
+ BAD_FOOD_CHAR,
+ EATEN_FOOD_CHAR,
+ GOLDEN_AGE_CHAR,
+ ANGRY_POP_CHAR,
+ OPEN_BORDERS_CHAR,
+ DEFENSIVE_PACT_CHAR,
+ MAP_CHAR,
+ OCCUPATION_CHAR,
+ POWER_CHAR,
+
+#ifdef _USRDLL
+ MAX_NUM_SYMBOLS
+#endif
+};
+
+enum HandicapTypes // Exposed to Python
+{
+ NO_HANDICAP = -1,
+};
+
+enum GameSpeedTypes // Exposed to Python
+{
+ NO_GAMESPEED = -1,
+};
+
+enum TurnTimerTypes // Exposed to Python
+{
+ NO_TURNTIMER = -1,
+};
+
+enum EraTypes // Exposed to Python
+{
+ NO_ERA = -1,
+};
+
+enum CivilizationTypes // Exposed to Python
+{
+ NO_CIVILIZATION = -1,
+};
+
+enum LeaderHeadTypes // Exposed to Python
+{
+ NO_LEADER = -1,
+};
+
+// Used for managing Art Differences based on nationality
+enum ArtStyleTypes // Exposed to Python
+{
+ NO_ARTSTYLE = -1,
+};
+
+enum UnitArtStyleTypes
+{
+ NO_UNIT_ARTSTYLE = -1,
+};
+
+enum CitySizeTypes // Exposed to Python
+{
+ NO_CITYSIZE = -1,
+
+ CITYSIZE_SMALL,
+ CITYSIZE_MEDIUM,
+ CITYSIZE_LARGE,
+
+#ifdef _USRDLL
+ NUM_CITYSIZE_TYPES
+#endif
+};
+
+enum FootstepAudioTypes // Exposed to Python
+{
+ NO_FOOTSTEPAUDIO = -1,
+};
+
+enum FootstepAudioTags // Exposed to Python
+{
+ NO_FOOTSTEPAUDIO_TAG = -1,
+};
+
+enum ChatTargetTypes // Exposed to Python
+{
+ NO_CHATTARGET = -1,
+ CHATTARGET_ALL = -2,
+ CHATTARGET_TEAM = -3,
+};
+
+enum VoiceTargetTypes // Exposed to Python
+{
+ NO_VOICETARGET = -1,
+
+ VOICETARGET_DIPLO,
+ VOICETARGET_TEAM,
+ VOICETARGET_ALL,
+
+#ifdef _USRDLL
+ NUM_VOICETARGETS
+#endif
+};
+
+enum TeamTypes // Exposed to Python
+{
+ NO_TEAM = -1,
+};
+
+enum PlayerTypes // Exposed to Python
+{
+ NO_PLAYER = -1,
+};
+
+enum TraitTypes // Exposed to Python
+{
+ NO_TRAIT = -1,
+};
+
+enum OrderTypes // Exposed to Python
+{
+ NO_ORDER = -1,
+
+ ORDER_TRAIN,
+ ORDER_CONSTRUCT,
+ ORDER_CREATE,
+ ORDER_MAINTAIN,
+
+#ifdef _USRDLL
+ NUM_ORDER_TYPES
+#endif
+};
+
+enum TaskTypes // Exposed to Python
+{
+ NO_TASK = -1,
+
+ TASK_RAZE,
+ TASK_DISBAND,
+ TASK_GIFT,
+ TASK_SET_AUTOMATED_CITIZENS,
+ TASK_SET_AUTOMATED_PRODUCTION,
+ TASK_SET_EMPHASIZE,
+ TASK_CHANGE_SPECIALIST,
+ TASK_CHANGE_WORKING_PLOT,
+ TASK_CLEAR_WORKING_OVERRIDE,
+ TASK_HURRY,
+ TASK_CONSCRIPT,
+ TASK_CLEAR_ORDERS,
+ TASK_RALLY_PLOT,
+ TASK_CLEAR_RALLY_PLOT,
+ TASK_LIBERATE,
+
+#ifdef _USRDLL
+ NUM_TASK_TYPES
+#endif
+};
+
+enum BuildingClassTypes // Exposed to Python
+{
+ NO_BUILDINGCLASS = -1,
+};
+
+enum BuildingTypes // Exposed to Python
+{
+ NO_BUILDING = -1,
+};
+
+enum SpecialBuildingTypes // Exposed to Python
+{
+ NO_SPECIALBUILDING = -1,
+};
+
+enum ProjectTypes // Exposed to Python
+{
+ NO_PROJECT = -1,
+};
+
+enum AxisTypes
+{
+ AXIS_X,
+ AXIS_Y,
+ AXIS_Z,
+ NUM_AXIS_TYPES
+};
+
+enum SpaceShipInfoTypes
+{
+ SPACE_SHIP_INFO_TYPE_NONE,
+ SPACE_SHIP_INFO_TYPE_FILENAME,
+ SPACE_SHIP_INFO_TYPE_ALPHA_CENTAURI,
+ SPACE_SHIP_INFO_TYPE_LAUNCH,
+ SPACE_SHIP_INFO_TYPE_LAUNCHED,
+ SPACE_SHIP_INFO_TYPE_ZOOM_IN,
+ SPACE_SHIP_INFO_TYPE_ZOOM_MOVE,
+ SPACE_SHIP_INFO_TYPE_COMPONENT_OFF,
+ SPACE_SHIP_INFO_TYPE_COMPONENT_PREVIEW,
+ SPACE_SHIP_INFO_TYPE_COMPONENT_APPEAR,
+ SPACE_SHIP_INFO_TYPE_COMPONENT_ON,
+ SPACE_SHIP_INFO_TYPE_LIGHT_OFF,
+ SPACE_SHIP_INFO_TYPE_GANTRY_SMOKE_ON,
+ SPACE_SHIP_INFO_TYPE_IN_SPACE_SMOKE_ON,
+ SPACE_SHIP_INFO_TYPE_IN_GAME_SMOKE_ON,
+ NUM_SPACE_SHIP_INFO_TYPES
+};
+
+enum ProcessTypes // Exposed to Python
+{
+ NO_PROCESS = -1,
+};
+
+enum VoteTypes // Exposed to Python
+{
+ NO_VOTE = -1,
+};
+
+enum PlayerVoteTypes // Exposed to Python
+{
+ NO_PLAYER_VOTE_CHECKED = -6,
+ PLAYER_VOTE_NEVER = -5,
+ PLAYER_VOTE_ABSTAIN = -4,
+ PLAYER_VOTE_NO = -3,
+ PLAYER_VOTE_YES = -2,
+ NO_PLAYER_VOTE = -1
+};
+
+enum InfoBarTypes // Exposed to Python
+{
+ INFOBAR_STORED,
+ INFOBAR_RATE,
+ INFOBAR_RATE_EXTRA,
+ INFOBAR_EMPTY,
+
+#ifdef _USRDLL
+ NUM_INFOBAR_TYPES
+#endif
+};
+
+enum HealthBarTypes // Exposed to Python
+{
+ HEALTHBAR_ALIVE_ATTACK,
+ HEALTHBAR_ALIVE_DEFEND,
+ HEALTHBAR_DEAD,
+
+#ifdef _USRDLL
+ NUM_HEALTHBAR_TYPES
+#endif
+};
+
+enum ConceptTypes // Exposed to Python
+{
+ NO_CONCEPT = -1,
+};
+
+enum NewConceptTypes // Exposed to Python
+{
+ NO_NEW_CONCEPT = -1,
+};
+
+enum CalendarTypes // Exposed to Python
+{
+ NO_CALENDAR = -1,
+
+ CALENDAR_DEFAULT,
+ CALENDAR_BI_YEARLY,
+ CALENDAR_YEARS,
+ CALENDAR_TURNS,
+ CALENDAR_SEASONS,
+ CALENDAR_MONTHS,
+ CALENDAR_WEEKS,
+};
+
+enum SeasonTypes // Exposed to Python
+{
+ NO_SEASON = -1,
+};
+
+enum MonthTypes // Exposed to Python
+{
+ NO_MONTH = -1,
+};
+
+enum DenialTypes // Exposed to Python
+{
+ NO_DENIAL = -1,
+
+ DENIAL_UNKNOWN,
+ DENIAL_NEVER,
+ DENIAL_TOO_MUCH,
+ DENIAL_MYSTERY,
+ DENIAL_JOKING,
+ DENIAL_ANGER_CIVIC,
+ DENIAL_FAVORITE_CIVIC,
+ DENIAL_MINORITY_RELIGION,
+ DENIAL_CONTACT_THEM,
+ DENIAL_VICTORY,
+ DENIAL_ATTITUDE,
+ DENIAL_ATTITUDE_THEM,
+ DENIAL_TECH_WHORE,
+ DENIAL_TECH_MONOPOLY,
+ DENIAL_POWER_US,
+ DENIAL_POWER_YOU,
+ DENIAL_POWER_THEM,
+ DENIAL_TOO_MANY_WARS,
+ DENIAL_NO_GAIN,
+ DENIAL_NOT_ALLIED,
+ DENIAL_RECENT_CANCEL,
+ DENIAL_WORST_ENEMY,
+ DENIAL_POWER_YOUR_ENEMIES,
+ DENIAL_TOO_FAR,
+ DENIAL_VASSAL,
+ DENIAL_WAR_NOT_POSSIBLE_US,
+ DENIAL_WAR_NOT_POSSIBLE_YOU,
+ DENIAL_PEACE_NOT_POSSIBLE_US,
+ DENIAL_PEACE_NOT_POSSIBLE_YOU
+};
+
+enum DomainTypes // Exposed to Python
+{
+ NO_DOMAIN = -1,
+
+ DOMAIN_SEA,
+ DOMAIN_AIR,
+ DOMAIN_LAND,
+ DOMAIN_IMMOBILE,
+
+#ifdef _USRDLL
+ NUM_DOMAIN_TYPES
+#endif
+};
+
+enum UnitClassTypes // Exposed to Python
+{
+ NO_UNITCLASS = -1,
+};
+
+enum UnitTypes // Exposed to Python
+{
+ NO_UNIT = -1,
+};
+
+enum SpecialUnitTypes // Exposed to Python
+{
+ NO_SPECIALUNIT = -1,
+};
+
+enum UnitCombatTypes // Exposed to Python
+{
+ NO_UNITCOMBAT = -1,
+};
+
+enum UnitAITypes // Exposed to Python
+{
+ NO_UNITAI = -1,
+
+ UNITAI_UNKNOWN,
+ UNITAI_ANIMAL,
+ UNITAI_SETTLE,
+ UNITAI_WORKER,
+ UNITAI_ATTACK,
+ UNITAI_ATTACK_CITY,
+ UNITAI_COLLATERAL,
+ UNITAI_PILLAGE,
+ UNITAI_RESERVE,
+ UNITAI_COUNTER,
+ UNITAI_CITY_DEFENSE,
+ UNITAI_CITY_COUNTER,
+ UNITAI_CITY_SPECIAL,
+ UNITAI_EXPLORE,
+ UNITAI_MISSIONARY,
+ UNITAI_PROPHET,
+ UNITAI_ARTIST,
+ UNITAI_SCIENTIST,
+ UNITAI_GENERAL,
+ UNITAI_MERCHANT,
+ UNITAI_ENGINEER,
+ UNITAI_SPY,
+ UNITAI_ICBM,
+ UNITAI_WORKER_SEA,
+ UNITAI_ATTACK_SEA,
+ UNITAI_RESERVE_SEA,
+ UNITAI_ESCORT_SEA,
+ UNITAI_EXPLORE_SEA,
+ UNITAI_ASSAULT_SEA,
+ UNITAI_SETTLER_SEA,
+ UNITAI_MISSIONARY_SEA,
+ UNITAI_SPY_SEA,
+ UNITAI_CARRIER_SEA,
+ UNITAI_MISSILE_CARRIER_SEA,
+ UNITAI_PIRATE_SEA,
+ UNITAI_ATTACK_AIR,
+ UNITAI_DEFENSE_AIR,
+ UNITAI_CARRIER_AIR,
+ UNITAI_MISSILE_AIR,
+ UNITAI_PARADROP,
+ UNITAI_ATTACK_CITY_LEMMING,
+
+ NUM_UNITAI_TYPES
+};
+
+enum InvisibleTypes // Exposed to Python
+{
+ NO_INVISIBLE = -1,
+};
+
+enum VoteSourceTypes // Exposed to Python
+{
+ NO_VOTESOURCE = -1,
+};
+
+enum ProbabilityTypes // Exposed to Python
+{
+ NO_PROBABILITY = -1,
+
+ PROBABILITY_LOW,
+ PROBABILITY_REAL,
+ PROBABILITY_HIGH,
+};
+
+enum ActivityTypes // Exposed to Python
+{
+ NO_ACTIVITY = -1,
+
+ ACTIVITY_AWAKE,
+ ACTIVITY_HOLD,
+ ACTIVITY_SLEEP,
+ ACTIVITY_HEAL,
+ ACTIVITY_SENTRY,
+ ACTIVITY_INTERCEPT,
+ ACTIVITY_MISSION,
+ ACTIVITY_PATROL,
+ ACTIVITY_PLUNDER,
+
+#ifdef _USRDLL
+ NUM_ACTIVITY_TYPES
+#endif
+};
+
+enum AutomateTypes // Exposed to Python
+{
+ NO_AUTOMATE = -1,
+
+ AUTOMATE_BUILD,
+ AUTOMATE_NETWORK,
+ AUTOMATE_CITY,
+ AUTOMATE_EXPLORE,
+ AUTOMATE_RELIGION,
+
+#ifdef _USRDLL
+ NUM_AUTOMATE_TYPES
+#endif
+};
+
+// any additions need to be reflected in GlobalTypes.xml
+enum MissionTypes // Exposed to Python
+{
+ NO_MISSION = -1,
+
+ MISSION_MOVE_TO,
+ MISSION_ROUTE_TO,
+ MISSION_MOVE_TO_UNIT,
+ MISSION_SKIP,
+ MISSION_SLEEP,
+ MISSION_FORTIFY,
+ MISSION_PLUNDER,
+ MISSION_AIRPATROL,
+ MISSION_SEAPATROL,
+ MISSION_HEAL,
+ MISSION_SENTRY,
+ MISSION_AIRLIFT,
+ MISSION_NUKE,
+ MISSION_RECON,
+ MISSION_PARADROP,
+ MISSION_AIRBOMB,
+ MISSION_RANGE_ATTACK,
+ MISSION_BOMBARD,
+ MISSION_PILLAGE,
+ MISSION_SABOTAGE,
+ MISSION_DESTROY,
+ MISSION_STEAL_PLANS,
+ MISSION_FOUND,
+ MISSION_SPREAD,
+ MISSION_SPREAD_CORPORATION,
+ MISSION_JOIN,
+ MISSION_CONSTRUCT,
+ MISSION_DISCOVER,
+ MISSION_HURRY,
+ MISSION_TRADE,
+ MISSION_GREAT_WORK,
+ MISSION_INFILTRATE,
+ MISSION_GOLDEN_AGE,
+ MISSION_BUILD,
+ MISSION_LEAD,
+ MISSION_ESPIONAGE,
+ MISSION_DIE_ANIMATION,
+
+ MISSION_BEGIN_COMBAT,
+ MISSION_END_COMBAT,
+ MISSION_AIRSTRIKE,
+ MISSION_SURRENDER,
+ MISSION_CAPTURED,
+ MISSION_IDLE,
+ MISSION_DIE,
+ MISSION_DAMAGE,
+ MISSION_MULTI_SELECT,
+ MISSION_MULTI_DESELECT,
+
+#ifdef _USRDLL
+ NUM_MISSION_TYPES
+#endif
+};
+
+enum MissionAITypes // Exposed to Python
+{
+ NO_MISSIONAI = -1,
+
+ MISSIONAI_SHADOW,
+ MISSIONAI_GROUP,
+ MISSIONAI_LOAD_ASSAULT,
+ MISSIONAI_LOAD_SETTLER,
+ MISSIONAI_LOAD_SPECIAL,
+ MISSIONAI_GUARD_CITY,
+ MISSIONAI_GUARD_BONUS,
+ MISSIONAI_GUARD_TRADE_NET,
+ MISSIONAI_GUARD_SPY,
+ MISSIONAI_ATTACK_SPY,
+ MISSIONAI_SPREAD,
+ MISSIONAI_SPREAD_CORPORATION,
+ MISSIONAI_CONSTRUCT,
+ MISSIONAI_HURRY,
+ MISSIONAI_GREAT_WORK,
+ MISSIONAI_EXPLORE,
+ MISSIONAI_BLOCKADE,
+ MISSIONAI_PILLAGE,
+ MISSIONAI_FOUND,
+ MISSIONAI_BUILD,
+ MISSIONAI_ASSAULT,
+ MISSIONAI_CARRIER,
+ MISSIONAI_PICKUP
+};
+
+// any additions need to be reflected in GlobalTypes.xml
+enum CommandTypes // Exposed to Python
+{
+ NO_COMMAND = -1,
+
+ COMMAND_PROMOTION,
+ COMMAND_UPGRADE,
+ COMMAND_AUTOMATE,
+ COMMAND_WAKE,
+ COMMAND_CANCEL,
+ COMMAND_CANCEL_ALL,
+ COMMAND_STOP_AUTOMATION,
+ COMMAND_DELETE,
+ COMMAND_GIFT,
+ COMMAND_LOAD,
+ COMMAND_LOAD_UNIT,
+ COMMAND_UNLOAD,
+ COMMAND_UNLOAD_ALL,
+ COMMAND_HOTKEY,
+
+#ifdef _USRDLL
+ NUM_COMMAND_TYPES
+#endif
+};
+
+enum ControlTypes // Exposed to Python
+{
+ NO_CONTROL = -1,
+
+ CONTROL_CENTERONSELECTION,
+ CONTROL_SELECTYUNITTYPE,
+ CONTROL_SELECTYUNITALL,
+ CONTROL_SELECTCITY,
+ CONTROL_SELECTCAPITAL,
+ CONTROL_NEXTCITY,
+ CONTROL_PREVCITY,
+ CONTROL_NEXTUNIT,
+ CONTROL_PREVUNIT,
+ CONTROL_CYCLEUNIT,
+ CONTROL_CYCLEUNIT_ALT,
+ CONTROL_CYCLEWORKER,
+ CONTROL_LASTUNIT,
+ CONTROL_ENDTURN,
+ CONTROL_ENDTURN_ALT,
+ CONTROL_FORCEENDTURN,
+ CONTROL_AUTOMOVES,
+ CONTROL_PING,
+ CONTROL_SIGN,
+ CONTROL_GRID,
+ CONTROL_BARE_MAP,
+ CONTROL_YIELDS,
+ CONTROL_RESOURCE_ALL,
+ CONTROL_UNIT_ICONS,
+ CONTROL_GLOBELAYER,
+ CONTROL_SCORES,
+ CONTROL_LOAD_GAME,
+ CONTROL_OPTIONS_SCREEN,
+ CONTROL_RETIRE,
+ CONTROL_SAVE_GROUP,
+ CONTROL_SAVE_NORMAL,
+ CONTROL_QUICK_SAVE,
+ CONTROL_QUICK_LOAD,
+ CONTROL_ORTHO_CAMERA,
+ CONTROL_CYCLE_CAMERA_FLYING_MODES,
+ CONTROL_ISOMETRIC_CAMERA_LEFT,
+ CONTROL_ISOMETRIC_CAMERA_RIGHT,
+ CONTROL_FLYING_CAMERA,
+ CONTROL_MOUSE_FLYING_CAMERA,
+ CONTROL_TOP_DOWN_CAMERA,
+ CONTROL_CIVILOPEDIA,
+ CONTROL_RELIGION_SCREEN,
+ CONTROL_CORPORATION_SCREEN,
+ CONTROL_CIVICS_SCREEN,
+ CONTROL_FOREIGN_SCREEN,
+ CONTROL_FINANCIAL_SCREEN,
+ CONTROL_MILITARY_SCREEN,
+ CONTROL_TECH_CHOOSER,
+ CONTROL_TURN_LOG,
+ CONTROL_CHAT_ALL,
+ CONTROL_CHAT_TEAM,
+ CONTROL_DOMESTIC_SCREEN,
+ CONTROL_VICTORY_SCREEN,
+ CONTROL_INFO,
+ CONTROL_GLOBE_VIEW,
+ CONTROL_DETAILS,
+ CONTROL_ADMIN_DETAILS,
+ CONTROL_HALL_OF_FAME,
+ CONTROL_WORLD_BUILDER,
+ CONTROL_DIPLOMACY,
+ CONTROL_SELECT_HEALTHY,
+ CONTROL_ESPIONAGE_SCREEN,
+ CONTROL_FREE_COLONY,
+
+#ifdef _USRDLL
+ NUM_CONTROL_TYPES
+#endif
+};
+
+enum PromotionTypes // Exposed to Python
+{
+ NO_PROMOTION = -1,
+};
+
+enum TechTypes // Exposed to Python
+{
+ NO_TECH = -1,
+};
+
+enum SpecialistTypes // Exposed to Python
+{
+ NO_SPECIALIST = -1,
+};
+
+enum ReligionTypes // Exposed to Python
+{
+ NO_RELIGION = -1,
+};
+
+enum CorporationTypes // Exposed to Python
+{
+ NO_CORPORATION = -1,
+};
+
+enum HurryTypes // Exposed to Python
+{
+ NO_HURRY = -1,
+};
+
+enum UpkeepTypes // Exposed to Python
+{
+ NO_UPKEEP = -1,
+};
+
+enum CultureLevelTypes // Exposed to Python
+{
+ NO_CULTURELEVEL = -1,
+};
+
+enum CivicOptionTypes // Exposed to Python
+{
+ NO_CIVICOPTION = -1,
+};
+
+enum CivicTypes // Exposed to Python
+{
+ NO_CIVIC = -1,
+};
+
+enum WarPlanTypes // Exposed to Python
+{
+ NO_WARPLAN = -1,
+
+ WARPLAN_ATTACKED_RECENT,
+ WARPLAN_ATTACKED,
+ WARPLAN_PREPARING_LIMITED,
+ WARPLAN_PREPARING_TOTAL,
+ WARPLAN_LIMITED,
+ WARPLAN_TOTAL,
+ WARPLAN_DOGPILE
+};
+
+enum AreaAITypes // Exposed to Python
+{
+ NO_AREAAI = -1,
+
+ AREAAI_OFFENSIVE,
+ AREAAI_DEFENSIVE,
+ AREAAI_MASSING,
+ AREAAI_ASSAULT,
+ AREAAI_ASSAULT_MASSING,
+ AREAAI_ASSAULT_ASSIST,
+ AREAAI_NEUTRAL
+};
+
+enum EndTurnButtonStates // Exposed to Python
+{
+ END_TURN_GO,
+ END_TURN_OVER_HIGHLIGHT,
+ END_TURN_OVER_DARK,
+
+#ifdef _USRDLL
+ NUM_END_TURN_STATES
+#endif
+};
+
+enum FogOfWarModeTypes // Exposed to Python
+{
+ FOGOFWARMODE_OFF,
+ FOGOFWARMODE_UNEXPLORED,
+ FOGOFWARMODE_NOVIS,
+
+#ifdef _USRDLL
+ NUM_FOGOFWARMODE_TYPES
+#endif
+};
+
+enum FogTypes
+{
+ FOG_TYPE_NONE,
+ FOG_TYPE_PARALLEL,
+ FOG_TYPE_PROJECTED,
+ NUM_FOG_TYPES
+};
+
+enum CameraOverlayTypes
+{
+ CAMERA_OVERLAY_DECAL,
+ CAMERA_OVERLAY_ADDITIVE,
+ NUM_CAMERA_OVERLAY_TYPES
+};
+
+enum FOWUpdateTypes
+{
+ FOW_UPDATE_REGULAR,
+ FOW_UPDATE_IMMEDIATE,
+ FOW_UPDATE_UNDO_IMMEDIATE,
+ FOW_UPDATE_FORCE_CHANGE,
+ NUM_FOW_UPDATE_TYPES
+};
+
+// AnimationTypes is depreciated, and will be eventually removed.
+// BONUSANIMATION_* and IMPROVEMENTANIMATION_* are still used, and will be left.
+
+enum AnimationTypes // Exposed to Python
+{
+ NONE_ANIMATION = -1, // NO_ANIMATION is used by FirePlace
+
+ BONUSANIMATION_UNIMPROVED = 1,
+ BONUSANIMATION_NOT_WORKED,
+ BONUSANIMATION_WORKED,
+
+ IMPROVEMENTANIMATION_OFF = 2,
+ IMPROVEMENTANIMATION_ON,
+ IMPROVEMENTANIMATION_OFF_EXTRA,
+ IMPROVEMENTANIMATION_ON_EXTRA_1,
+ IMPROVEMENTANIMATION_ON_EXTRA_2,
+ IMPROVEMENTANIMATION_ON_EXTRA_3,
+ IMPROVEMENTANIMATION_ON_EXTRA_4,
+};
+
+enum EntityEventTypes // Exposed to Python
+{
+ ENTITY_EVENT_NONE = -1, //!< Invalid event
+};
+
+enum AnimationPathTypes // Exposed to Python
+{
+ ANIMATIONPATH_NONE = -1,
+
+ // Default animation paths
+ ANIMATIONPATH_IDLE,
+ ANIMATIONPATH_MOVE,
+ ANIMATIONPATH_DAMAGE, //!< Updates the damage state for the unit
+
+ // Combat related animation paths
+ ANIMATIONPATH_RANDOMIZE_ANIMATION_SET,
+ ANIMATIONPATH_NUKE_STRIKE,
+ ANIMATIONPATH_MELEE_STRIKE,
+ ANIMATIONPATH_MELEE_HURT,
+ ANIMATIONPATH_MELEE_DIE,
+ ANIMATIONPATH_MELEE_FORTIFIED,
+ ANIMATIONPATH_MELEE_DIE_FADE, //!< Used only in combat. The colateral damage die should have a fade integrated.
+ ANIMATIONPATH_MELEE_FLEE, //!< Used only by settler children, so they don't die in combat
+
+ // Ranged combat related animation paths
+ ANIMATIONPATH_RANGED_STRIKE,
+ ANIMATIONPATH_RANGED_DIE,
+ ANIMATIONPATH_RANGED_FORTIFIED,
+ ANIMATIONPATH_RANGED_RUNHIT,
+ ANIMATIONPATH_RANGED_RUNDIE,
+ ANIMATIONPATH_RANGED_DIE_FADE, //!< Used only in combat. The colateral damage die should have a fade integrated.
+ ANIMATIONPATH_LEADER_COMMAND,
+
+ // Air Units animation paths
+ ANIMATIONPATH_AIRFADEIN,
+ ANIMATIONPATH_AIRFADEOUT,
+ ANIMATIONPATH_AIRSTRIKE,
+ ANIMATIONPATH_AIRBOMB,
+
+ //mission related animation paths
+ ANIMATIONPATH_HEAL,
+ ANIMATIONPATH_SLEEP,
+ ANIMATIONPATH_FORTIFY,
+ ANIMATIONPATH_MELEE_FORTIFY,
+ ANIMATIONPATH_PILLAGE,
+ ANIMATIONPATH_SENTRY,
+ ANIMATIONPATH_FOUND,
+ ANIMATIONPATH_IRRIGATE,
+ ANIMATIONPATH_BUILD,
+ ANIMATIONPATH_MINE,
+ ANIMATIONPATH_CHOP,
+ ANIMATIONPATH_SHOVEL,
+ ANIMATIONPATH_RAILROAD,
+ ANIMATIONPATH_SABOTAGE,
+ ANIMATIONPATH_DESTROY,
+ ANIMATIONPATH_STEAL_PLANS,
+ ANIMATIONPATH_GREAT_EVENT,
+ ANIMATIONPATH_SURRENDER,
+ ANIMATIONPATH_AIRPATROL,
+};
+
+//!< Enumeration for the animation category types.
+enum AnimationCategoryTypes // Exposed to Python
+{
+ ANIMCAT_NONE = -1,
+};
+
+//!< Animation category operators.
+enum AnimationOperatorTypes
+{
+ ANIMOP_FIRST = 1001,
+ ANIMOP_RAND_FPR = ANIMOP_FIRST, //!< Sets the FPR to a random number [0..1].
+ ANIMOP_SET_FPR, //!< Sets the FPR to the input value
+ ANIMOP_SET_BR, //!< Sets the BR to true the input value is non-zero
+ ANIMOP_ADD_FPR, //!< Adds the input value to the FPR register (input can be negative)
+ ANIMOP_TEST_GT, //!< Sets/resets the BR if the FPR is greater than the input
+ ANIMOP_TEST_LT, //!< Sets/resets the BR if the FPR is less than the input
+ ANIMOP_LOAD_CAS, //!< Sets the FPR to the CAS/32.
+ ANIMOP_SET_ANIMATION_SET, //!< Modifies the current animation set, by setting it to ((FPR*32)%32)
+ ANIMOP_SKIP_IF, //!< Skips the given number of instructions if the BR is true
+ ANIMOP_CAS_INCR, //!< Increments the CAS (and resets to zero if it is the maximum)
+ ANIMOP_IS_RANGED, //!< Sets the BR to true if the unit is "ranged", and to false otherwise
+ ANIMOP_DEACTIVATE_DAMAGE_LAYERS, //!< Deactivates all animations that are layered
+ ANIMOP_SETCAS_DAMAGE, //!< Set the current animation set to the damage level of the unit (damage/art define max)
+ ANIMOP_LAST
+};
+
+enum CursorTypes // Exposed to Python
+{
+ NO_CURSOR = -1,
+};
+
+enum FunctionTypes
+{
+ FUNC_NOINTERP = 0, // NiAnimationKey::NOINTERP,
+ FUNC_LINKEY, // = NiAnimationKey::LINKEY,
+ FUNC_BEZKEY, // = NiAnimationKey::BEZKEY,
+ FUNC_TCBKEY, // = NiAnimationKey::TCBKEY,
+ FUNC_EULERKEY, // = NiAnimationKey::EULERKEY,
+ FUNC_STEPKEY, // = NiAnimationKey::STEPKEY,
+
+#ifdef _USRDLL
+ NUM_FUNC_TYPES // = NiAnimationKey::NUMKEYTYPES
+#endif
+};
+
+enum TradeableItems // Exposed to Python
+{
+ TRADE_ITEM_NONE = -1,
+
+ TRADE_GOLD,
+ TRADE_GOLD_PER_TURN,
+ TRADE_MAPS,
+ TRADE_VASSAL,
+ TRADE_SURRENDER,
+ TRADE_OPEN_BORDERS,
+ TRADE_DEFENSIVE_PACT,
+ TRADE_PERMANENT_ALLIANCE,
+ TRADE_PEACE_TREATY,
+
+#ifdef _USRDLL
+ NUM_BASIC_ITEMS,
+
+ TRADE_TECHNOLOGIES = NUM_BASIC_ITEMS,
+#else
+ TRADE_TECHNOLOGIES,
+#endif
+
+ TRADE_RESOURCES,
+ TRADE_CITIES,
+ TRADE_PEACE,
+ TRADE_WAR,
+ TRADE_EMBARGO,
+ TRADE_CIVIC,
+ TRADE_RELIGION,
+
+#ifdef _USRDLL
+ NUM_TRADEABLE_HEADINGS,
+
+ NUM_TRADEABLE_ITEMS = NUM_TRADEABLE_HEADINGS,
+#endif
+};
+
+enum DiploEventTypes // Exposed to Python
+{
+ NO_DIPLOEVENT = -1,
+
+ DIPLOEVENT_CONTACT,
+ DIPLOEVENT_AI_CONTACT,
+ DIPLOEVENT_FAILED_CONTACT,
+ DIPLOEVENT_GIVE_HELP,
+ DIPLOEVENT_REFUSED_HELP,
+ DIPLOEVENT_ACCEPT_DEMAND,
+ DIPLOEVENT_REJECTED_DEMAND,
+ DIPLOEVENT_DEMAND_WAR,
+ DIPLOEVENT_CONVERT,
+ DIPLOEVENT_NO_CONVERT,
+ DIPLOEVENT_REVOLUTION,
+ DIPLOEVENT_NO_REVOLUTION,
+ DIPLOEVENT_JOIN_WAR,
+ DIPLOEVENT_NO_JOIN_WAR,
+ DIPLOEVENT_STOP_TRADING,
+ DIPLOEVENT_NO_STOP_TRADING,
+ DIPLOEVENT_ASK_HELP,
+ DIPLOEVENT_MADE_DEMAND,
+ DIPLOEVENT_RESEARCH_TECH,
+ DIPLOEVENT_TARGET_CITY,
+ DIPLOEVENT_MADE_DEMAND_VASSAL,
+
+#ifdef _USRDLL
+ NUM_DIPLOEVENT_TYPES
+#endif
+};
+
+enum DiploCommentTypes // Exposed to Python
+{
+ NO_DIPLOCOMMENT = -1
+};
+
+enum NetContactTypes // Exposed to Python
+{
+ NO_NETCONTACT = -1,
+ NETCONTACT_INITIAL,
+ NETCONTACT_RESPONSE,
+ NETCONTACT_ESTABLISHED,
+ NETCONTACT_BUSY,
+
+#ifdef _USRDLL
+ NUM_NETCONTACT_TYPES
+#endif
+};
+
+enum ContactTypes // Exposed to Python
+{
+ CONTACT_RELIGION_PRESSURE,
+ CONTACT_CIVIC_PRESSURE,
+ CONTACT_JOIN_WAR,
+ CONTACT_STOP_TRADING,
+ CONTACT_GIVE_HELP,
+ CONTACT_ASK_FOR_HELP,
+ CONTACT_DEMAND_TRIBUTE,
+ CONTACT_OPEN_BORDERS,
+ CONTACT_DEFENSIVE_PACT,
+ CONTACT_PERMANENT_ALLIANCE,
+ CONTACT_PEACE_TREATY,
+ CONTACT_TRADE_TECH,
+ CONTACT_TRADE_BONUS,
+ CONTACT_TRADE_MAP,
+
+ NUM_CONTACT_TYPES
+};
+
+enum MemoryTypes // Exposed to Python
+{
+ MEMORY_DECLARED_WAR,
+ MEMORY_DECLARED_WAR_ON_FRIEND,
+ MEMORY_HIRED_WAR_ALLY,
+ MEMORY_NUKED_US,
+ MEMORY_NUKED_FRIEND,
+ MEMORY_RAZED_CITY,
+ MEMORY_RAZED_HOLY_CITY,
+ MEMORY_SPY_CAUGHT,
+ MEMORY_GIVE_HELP,
+ MEMORY_REFUSED_HELP,
+ MEMORY_ACCEPT_DEMAND,
+ MEMORY_REJECTED_DEMAND,
+ MEMORY_ACCEPTED_RELIGION,
+ MEMORY_DENIED_RELIGION,
+ MEMORY_ACCEPTED_CIVIC,
+ MEMORY_DENIED_CIVIC,
+ MEMORY_ACCEPTED_JOIN_WAR,
+ MEMORY_DENIED_JOIN_WAR,
+ MEMORY_ACCEPTED_STOP_TRADING,
+ MEMORY_DENIED_STOP_TRADING,
+ MEMORY_STOPPED_TRADING,
+ MEMORY_STOPPED_TRADING_RECENT,
+ MEMORY_HIRED_TRADE_EMBARGO,
+ MEMORY_MADE_DEMAND,
+ MEMORY_MADE_DEMAND_RECENT,
+ MEMORY_CANCELLED_OPEN_BORDERS,
+ MEMORY_TRADED_TECH_TO_US,
+ MEMORY_RECEIVED_TECH_FROM_ANY,
+ MEMORY_VOTED_AGAINST_US,
+ MEMORY_VOTED_FOR_US,
+ MEMORY_EVENT_GOOD_TO_US,
+ MEMORY_EVENT_BAD_TO_US,
+ MEMORY_LIBERATED_CITIES,
+
+ NUM_MEMORY_TYPES
+};
+
+enum AttitudeTypes // Exposed to Python
+{
+ NO_ATTITUDE = -1,
+
+ ATTITUDE_FURIOUS,
+ ATTITUDE_ANNOYED,
+ ATTITUDE_CAUTIOUS,
+ ATTITUDE_PLEASED,
+ ATTITUDE_FRIENDLY,
+
+ NUM_ATTITUDE_TYPES
+};
+
+//! Enumeration for playing events with CvLeaderheadWidget
+enum LeaderheadAction // Exposed to Python
+{
+ NO_LEADERANIM = -1, //!< If used with CvLeaderheadWidget::PerformAction, plays the idle animation
+
+ LEADERANIM_GREETING, //!< The leaderhead greets you
+ LEADERANIM_FRIENDLY, //!< The leaderhead is friendly to you
+ LEADERANIM_PLEASED, //!< The leaderhead is pleased
+ LEADERANIM_CAUTIOUS, //!< The leaderhead is cautious
+ LEADERANIM_ANNOYED, //!< The leaderhead is annoyed
+ LEADERANIM_FURIOUS, //!< The leaderhead is furious
+ LEADERANIM_DISAGREE, //!< The leaderhead makes a disagree gesture
+ LEADERANIM_AGREE, //!< The leaderhead makes an agree gesture
+
+#ifdef _USRDLL
+ NUM_LEADERANIM_TYPES //!< The number of leaderhead event types
+#endif
+};
+
+enum DiplomacyPowerTypes // Exposed to Python
+{
+ NO_DIPLOMACYPOWER = -1,
+ DIPLOMACYPOWER_WEAKER,
+ DIPLOMACYPOWER_EQUAL,
+ DIPLOMACYPOWER_STRONGER,
+
+ NUM_DIPLOMACYPOWER_TYPES
+};
+
+enum FeatTypes // Exposed to Python
+{
+ FEAT_UNITCOMBAT_ARCHER,
+ FEAT_UNITCOMBAT_MOUNTED,
+ FEAT_UNITCOMBAT_MELEE,
+ FEAT_UNITCOMBAT_SIEGE,
+ FEAT_UNITCOMBAT_GUN,
+ FEAT_UNITCOMBAT_ARMOR,
+ FEAT_UNITCOMBAT_HELICOPTER,
+ FEAT_UNITCOMBAT_NAVAL,
+ FEAT_UNIT_PRIVATEER,
+ FEAT_UNIT_SPY,
+ FEAT_NATIONAL_WONDER,
+ FEAT_TRADE_ROUTE,
+ FEAT_COPPER_CONNECTED,
+ FEAT_HORSE_CONNECTED,
+ FEAT_IRON_CONNECTED,
+ FEAT_LUXURY_CONNECTED,
+ FEAT_FOOD_CONNECTED,
+ FEAT_POPULATION_HALF_MILLION,
+ FEAT_POPULATION_1_MILLION,
+ FEAT_POPULATION_2_MILLION,
+ FEAT_POPULATION_5_MILLION,
+ FEAT_POPULATION_10_MILLION,
+ FEAT_POPULATION_20_MILLION,
+ FEAT_POPULATION_50_MILLION,
+ FEAT_POPULATION_100_MILLION,
+ FEAT_POPULATION_200_MILLION,
+ FEAT_POPULATION_500_MILLION,
+ FEAT_POPULATION_1_BILLION,
+ FEAT_POPULATION_2_BILLION,
+ FEAT_CORPORATION_ENABLED,
+ FEAT_PAD,
+
+ NUM_FEAT_TYPES
+};
+
+enum SaveGameTypes // Exposed to Python
+{
+ SAVEGAME_NONE = -1,
+
+ SAVEGAME_AUTO,
+ SAVEGAME_RECOVERY,
+ SAVEGAME_QUICK,
+ SAVEGAME_NORMAL,
+ SAVEGAME_GROUP,
+ SAVEGAME_DROP_QUIT,
+ SAVEGAME_DROP_CONTINUE,
+ SAVEGAME_PBEM,
+ SAVEGAME_REPLAY,
+
+#ifdef _USRDLL
+ NUM_SAVEGAME_TYPES
+#endif
+};
+
+enum InitializationStates
+{
+ INIT_OK,
+ INIT_FAILED,
+
+#ifdef _USRDLL
+ NUM_INIT_STATES
+#endif
+};
+
+enum GameType // Exposed to Python
+{
+ GAME_NONE = -1,
+
+ GAME_SP_NEW,
+ GAME_SP_SCENARIO,
+ GAME_SP_LOAD,
+ GAME_MP_NEW,
+ GAME_MP_SCENARIO,
+ GAME_MP_LOAD,
+ GAME_HOTSEAT_NEW,
+ GAME_HOTSEAT_SCENARIO,
+ GAME_HOTSEAT_LOAD,
+ GAME_PBEM_NEW,
+ GAME_PBEM_SCENARIO,
+ GAME_PBEM_LOAD,
+ GAME_REPLAY,
+
+#ifdef _USRDLL
+ NUM_GAMETYPES
+#endif
+};
+
+enum GameMode // Exposed to Python
+{
+ NO_GAMEMODE = -1,
+
+ GAMEMODE_NORMAL,
+ GAMEMODE_PITBOSS,
+
+#ifdef _USRDLL
+ NUM_GAMEMODES
+#endif
+};
+
+enum GamePwdTypes
+{
+ NO_PWDTYPE = -1,
+
+ PWD_NEWGAME,
+ PWD_SCENARIO,
+ PWD_JOINGAME,
+
+#ifdef _USRDLL
+ NUM_PWDTYPES
+#endif
+};
+
+enum SlotClaim
+{
+ SLOTCLAIM_UNASSIGNED,
+ SLOTCLAIM_RESERVED,
+ SLOTCLAIM_ASSIGNED,
+
+#ifdef _USRDLL
+ NUM_SLOTCLAIMS
+#endif
+};
+
+enum SlotStatus
+{
+ SS_OPEN,
+ SS_COMPUTER,
+ SS_CLOSED,
+ SS_TAKEN,
+
+ SS_MAX_SLOT_STATUS,
+};
+
+enum InterfaceVisibility // Exposed to Python
+{
+ INTERFACE_SHOW,
+ INTERFACE_HIDE,
+ INTERFACE_HIDE_ALL,
+ INTERFACE_MINIMAP_ONLY,
+ INTERFACE_ADVANCED_START,
+};
+
+enum GenericButtonSizes // Exposed to Python
+{
+ BUTTON_SIZE_46,
+ BUTTON_SIZE_32,
+ BUTTON_SIZE_24,
+ BUTTON_SIZE_16,
+
+ BUTTON_SIZE_CUSTOM,
+};
+
+enum MenuScreenType
+{
+ MENU_SCREEN_STANDARD,
+ MENU_SCREEN_BASELOBBY,
+ MENU_SCREEN_BASE_SCENARIO,
+ MENU_SCREEN_JOIN,
+ MENU_SCREEN_BASE_LOAD,
+ MENU_SCREEN_LAUNCHING,
+ MENU_SCREEN_BASE_INIT,
+
+ MENU_SCREEN_OPENING_MENU,
+ MENU_SCREEN_MOD_MENU,
+
+ MENU_SCREEN_GS_BUDDYLIST,
+ MENU_SCREEN_GS_CHATROOM,
+ MENU_SCREEN_GS_CHANNEL,
+ MENU_SCREEN_GS_CHOOSE_SCENARIO,
+ MENU_SCREEN_GS_SCENARIO,
+ MENU_SCREEN_GS_NAVBAR,
+ MENU_SCREEN_GS_LOAD_STAGING,
+ MENU_SCREEN_GS_MOTD,
+ MENU_SCREEN_GS_LOGIN,
+ MENU_SCREEN_GS_LOAD,
+ MENU_SCREEN_GS_JOIN,
+ MENU_SCREEN_GS_INIT,
+ MENU_SCREEN_GS_CUSTOM_GAMES,
+
+ MENU_SCREEN_LANLOBBY,
+ MENU_SCREEN_MP_CHOOSE_SCENARIO,
+ MENU_SCREEN_MP_SCENARIO,
+ MENU_SCREEN_MP_LOAD_STAGING,
+ MENU_SCREEN_MP_LOAD,
+ MENU_SCREEN_MP_INIT,
+ MENU_SCREEN_MP_CHOICES,
+ MENU_SCREEN_MP_JOIN,
+
+ MENU_SCREEN_SP_WORLD_SIZE,
+ MENU_SCREEN_SP_SCENARIO,
+ MENU_SCREEN_SP_LOAD,
+ MENU_SCREEN_SP_INIT,
+ MENU_SCREEN_SP_CHOICES,
+ MENU_SCREEN_SP_ADVANCED_LOAD,
+ MENU_SCREEN_SP_SIMPLE_CIV_PICKER,
+ MENU_SCREEN_SP_REPLAY,
+ MENU_SCREEN_SP_MAP_SCRIPT,
+ MENU_SCREEN_SP_DIFFICULTY,
+};
+
+enum WorldBuilderPopupTypes // Exposed to Python
+{
+ WBPOPUP_NONE = -1,
+
+ WBPOPUP_START = 200,
+ WBPOPUP_CITY=WBPOPUP_START, // first entry, starts at 0
+ WBPOPUP_UNIT,
+ WBPOPUP_PLAYER,
+ WBPOPUP_PLOT,
+ WBPOPUP_TERRAIN,
+ WBPOPUP_FEATURE,
+ WBPOPUP_IMPROVEMENT,
+ WBPOPUP_GAME,
+
+#ifdef _USRDLL
+ NUM_WBPOPUP
+#endif
+};
+
+enum EventType // Exposed to Python
+{
+ // mouseEvent
+ EVT_LBUTTONDOWN = 1,
+ EVT_LBUTTONDBLCLICK,
+ EVT_RBUTTONDOWN,
+ EVT_BACK,
+ EVT_FORWARD,
+
+ // kbdEvent
+ EVT_KEYDOWN,
+ EVT_KEYUP,
+};
+
+// Different types of load
+enum LoadType // Exposed to Python
+{
+ LOAD_NORMAL,
+ LOAD_INIT,
+ LOAD_SETUP,
+ LOAD_GAMETYPE,
+ LOAD_REPLAY,
+ LOAD_NORMAL_AND_GAMETYPE,
+};
+
+// Available Fonts
+enum FontTypes // Exposed to Python
+{
+ TITLE_FONT,
+ GAME_FONT,
+ SMALL_FONT,
+ MENU_FONT,
+ MENU_HIGHLIGHT_FONT,
+};
+
+enum PanelStyles // Exposed to Python
+{
+ // Built in styles
+ PANEL_STYLE_STANDARD,
+ PANEL_STYLE_SOLID,
+ PANEL_STYLE_EMPTY,
+ PANEL_STYLE_FLAT,
+ PANEL_STYLE_IN,
+ PANEL_STYLE_OUT,
+ PANEL_STYLE_EXTERNAL,
+ PANEL_STYLE_DEFAULT,
+
+ // Civ specific styles
+ PANEL_STYLE_CIVILPEDIA,
+ PANEL_STYLE_STONE,
+ PANEL_STYLE_UNITSTAT,
+ PANEL_STYLE_BLUELARGE,
+ PANEL_STYLE_BLUE50,
+
+ PANEL_STYLE_TOPBAR,
+ PANEL_STYLE_BOTTOMBAR,
+ PANEL_STYLE_TECH,
+
+ PANEL_STYLE_GAMEHUD_LEFT,
+ PANEL_STYLE_GAMEHUD_RIGHT,
+ PANEL_STYLE_GAMEHUD_CENTER,
+ PANEL_STYLE_GAMEHUD_STATS,
+ PANEL_STYLE_GAME_MAP,
+ PANEL_STYLE_GAME_TOPBAR,
+ PANEL_STYLE_HUD_HELP,
+
+ PANEL_STYLE_CITY_LEFT,
+ PANEL_STYLE_CITY_RIGHT,
+ PANEL_STYLE_CITY_TOP,
+ PANEL_STYLE_CITY_TANSHADE,
+ PANEL_STYLE_CITY_INFO,
+ PANEL_STYLE_CITY_TANTL,
+ PANEL_STYLE_CITY_TANTR,
+ PANEL_STYLE_CITY_COLUMNL,
+ PANEL_STYLE_CITY_COLUMNC,
+ PANEL_STYLE_CITY_COLUMNR,
+ PANEL_STYLE_CITY_TITLE,
+
+ PANEL_STYLE_DAWN,
+ PANEL_STYLE_DAWNTOP,
+ PANEL_STYLE_DAWNBOTTOM,
+
+ PANEL_STYLE_MAIN,
+ PANEL_STYLE_MAIN_BLACK25,
+ PANEL_STYLE_MAIN_BLACK50,
+ PANEL_STYLE_MAIN_WHITE,
+ PANEL_STYLE_MAIN_WHITETAB,
+ PANEL_STYLE_MAIN_TAN,
+ PANEL_STYLE_MAIN_TAN15,
+ PANEL_STYLE_MAIN_TANL,
+ PANEL_STYLE_MAIN_TANR,
+ PANEL_STYLE_MAIN_TANT,
+ PANEL_STYLE_MAIN_TANB,
+ PANEL_STYLE_MAIN_BOTTOMBAR,
+ PANEL_STYLE_MAIN_SELECT,
+};
+
+enum ButtonStyles // Exposed to Python
+{
+ BUTTON_STYLE_STANDARD,
+ BUTTON_STYLE_ETCHED,
+ BUTTON_STYLE_FLAT,
+ BUTTON_STYLE_IMAGE,
+ BUTTON_STYLE_LABEL,
+ BUTTON_STYLE_LINK,
+ BUTTON_STYLE_SQUARE,
+ BUTTON_STYLE_TOOL,
+ BUTTON_STYLE_DEFAULT,
+
+ // Civ specific styles
+ BUTTON_STYLE_CIRCLE,
+ BUTTON_STYLE_CITY_B01,
+ BUTTON_STYLE_CITY_B02TL,
+ BUTTON_STYLE_CITY_B02TR,
+ BUTTON_STYLE_CITY_B02BL,
+ BUTTON_STYLE_CITY_B02BR,
+ BUTTON_STYLE_CITY_B03TL,
+ BUTTON_STYLE_CITY_B03TC,
+ BUTTON_STYLE_CITY_B03TR,
+ BUTTON_STYLE_CITY_B03BL,
+ BUTTON_STYLE_CITY_B03BC,
+ BUTTON_STYLE_CITY_B03BR,
+ BUTTON_STYLE_CITY_FLAT,
+ BUTTON_STYLE_CITY_PLUS,
+ BUTTON_STYLE_CITY_MINUS,
+
+ BUTTON_STYLE_ARROW_LEFT,
+ BUTTON_STYLE_ARROW_RIGHT
+};
+
+enum TableStyles // Exposed to Python
+{
+ TABLE_STYLE_STANDARD,
+ TABLE_STYLE_EMPTY,
+ TABLE_STYLE_ALTEMPTY,
+ TABLE_STYLE_CITY,
+ TABLE_STYLE_EMPTYSELECTINACTIVE,
+ TABLE_STYLE_ALTDEFAULT,
+ TABLE_STYLE_STAGINGROOM
+};
+
+enum EventContextTypes // Exposed to Python
+{
+ NO_EVENTCONTEXT = -1,
+
+ EVENTCONTEXT_SELF,
+ EVENTCONTEXT_ALL,
+};
+
+enum CivLoginStates
+{
+ NO_CIV_LOGIN = -1,
+
+ LOGIN_CIV_OK,
+ LOGIN_CIV_BAD_PWD,
+ LOGIN_CIV_TAKEN,
+ LOGIN_CIV_HAS_ID,
+};
+
+enum VersionTypes
+{
+ NO_VERSIONTYPE = -1,
+
+ VERSIONTYPE_EXE,
+ VERSIONTYPE_DLL,
+ VERSIONTYPE_SHADERS,
+ VERSIONTYPE_PYTHON,
+ VERSIONTYPE_XML,
+};
+
+enum VoteResultTypes
+{
+ VOTERESULT_MAJORITY,
+ VOTERESULT_UNANIMOUS,
+};
+
+enum VoteStatusTypes
+{
+ NO_VOTESTATUS = -1,
+
+ VOTESTATUS_TIED = -2,
+ VOTESTATUS_UNDECIDED = -3,
+ VOTESTATUS_INCOMPLETE = -4
+};
+
+// Tab Group in Options Menu
+enum TabGroupTypes // Exposed to Python
+{
+ NO_TABGROUP = -1,
+
+ TABGROUP_GAME,
+ TABGROUP_INPUT,
+ TABGROUP_GRAPHICS,
+ TABGROUP_AUDIO,
+ TABGROUP_CLOCK,
+
+#ifdef _USRDLL
+ NUM_TABGROUPS
+#endif
+};
+
+enum ReplayMessageTypes // Exposed to Python
+{
+ NO_REPLAY_MESSAGE = -1,
+
+ REPLAY_MESSAGE_MAJOR_EVENT,
+ REPLAY_MESSAGE_CITY_FOUNDED,
+ REPLAY_MESSAGE_PLOT_OWNER_CHANGE,
+
+#ifdef _USRDLL
+ NUM_REPLAY_MESSAGE_TYPES
+#endif
+};
+
+/*------------------------------------------------------------------------------------
+Enum: EAudioTag
+Purpose: To enumerate all of the tag strings loaded from the csv or xml files
+------------------------------------------------------------------------------------*/
+enum AudioTag // Exposed to Python
+{
+ AUDIOTAG_NONE = -1,
+ AUDIOTAG_SOUNDID,
+ AUDIOTAG_CONTEXTID,
+ AUDIOTAG_SOUNDTYPE,
+ AUDIOTAG_2DSCRIPT,
+ AUDIOTAG_3DSCRIPT,
+ AUDIOTAG_SOUNDSCAPE,
+ AUDIOTAG_POSITION,
+ AUDIOTAG_SCRIPTTYPE,
+ AUDIOTAG_LOADTYPE,
+ AUDIOTAG_COUNT,
+};
+
+enum CivilopediaPageTypes // Exposed to Python
+{
+ NO_CIVILOPEDIA_PAGE = -1,
+
+ CIVILOPEDIA_PAGE_TECH,
+ CIVILOPEDIA_PAGE_UNIT,
+ CIVILOPEDIA_PAGE_BUILDING,
+ CIVILOPEDIA_PAGE_WONDER,
+ CIVILOPEDIA_PAGE_TERRAIN,
+ CIVILOPEDIA_PAGE_FEATURE,
+ CIVILOPEDIA_PAGE_BONUS,
+ CIVILOPEDIA_PAGE_IMPROVEMENT,
+ CIVILOPEDIA_PAGE_SPECIALIST,
+ CIVILOPEDIA_PAGE_PROMOTION,
+ CIVILOPEDIA_PAGE_UNIT_GROUP,
+ CIVILOPEDIA_PAGE_CIV,
+ CIVILOPEDIA_PAGE_LEADER,
+ CIVILOPEDIA_PAGE_RELIGION,
+ CIVILOPEDIA_PAGE_CORPORATION,
+ CIVILOPEDIA_PAGE_CIVIC,
+ CIVILOPEDIA_PAGE_PROJECT,
+ CIVILOPEDIA_PAGE_CONCEPT,
+ CIVILOPEDIA_PAGE_CONCEPT_NEW,
+ CIVILOPEDIA_PAGE_HINTS,
+
+ NUM_CIVILOPEDIA_PAGE_TYPES
+};
+
+enum ActionSubTypes // Exposed to Python
+{
+ NO_ACTIONSUBTYPE = -1,
+
+ ACTIONSUBTYPE_INTERFACEMODE,
+ ACTIONSUBTYPE_COMMAND,
+ ACTIONSUBTYPE_BUILD,
+ ACTIONSUBTYPE_PROMOTION,
+ ACTIONSUBTYPE_UNIT,
+ ACTIONSUBTYPE_RELIGION,
+ ACTIONSUBTYPE_CORPORATION,
+ ACTIONSUBTYPE_SPECIALIST,
+ ACTIONSUBTYPE_BUILDING,
+ ACTIONSUBTYPE_CONTROL,
+ ACTIONSUBTYPE_AUTOMATE,
+ ACTIONSUBTYPE_MISSION,
+
+#ifdef _USRDLL
+ NUM_ACTIONSUBTYPES
+#endif
+};
+
+enum GameMessageTypes // Exposed to Python
+{
+ GAMEMESSAGE_NETWORK_READY,
+ GAMEMESSAGE_SAVE_GAME_FLAG,
+ GAMEMESSAGE_SAVE_FLAG_ACK,
+ GAMEMESSAGE_VERIFY_VERSION,
+ GAMEMESSAGE_VERSION_NACK,
+ GAMEMESSAGE_VERSION_WARNING,
+ GAMEMESSAGE_GAME_TYPE,
+ GAMEMESSAGE_ID_ASSIGNMENT,
+ GAMEMESSAGE_FILE_INFO,
+ GAMEMESSAGE_PICK_YOUR_CIV,
+ GAMEMESSAGE_CIV_CHOICE,
+ GAMEMESSAGE_CONFIRM_CIV_CLAIM,
+ GAMEMESSAGE_CLAIM_INFO,
+ GAMEMESSAGE_CIV_CHOICE_ACK,
+ GAMEMESSAGE_CIV_CHOICE_NACK,
+ GAMEMESSAGE_CIV_CHOSEN,
+ GAMEMESSAGE_INTERIM_NOTICE,
+ GAMEMESSAGE_INIT_INFO,
+ GAMEMESSAGE_MAPSCRIPT_CHECK,
+ GAMEMESSAGE_MAPSCRIPT_ACK,
+ GAMEMESSAGE_LOAD_GAME,
+ GAMEMESSAGE_PLAYER_ID,
+ GAMEMESSAGE_SLOT_REASSIGNMENT,
+ GAMEMESSAGE_PLAYER_INFO,
+ GAMEMESSAGE_GAME_INFO,
+ GAMEMESSAGE_REASSIGN_PLAYER,
+ GAMEMESSAGE_PITBOSS_INFO,
+ GAMEMESSAGE_LAUNCHING_INFO,
+ GAMEMESSAGE_INIT_GAME,
+ GAMEMESSAGE_INIT_PLAYERS,
+ GAMEMESSAGE_AUTH_REQUEST,
+ GAMEMESSAGE_AUTH_RESPONSE,
+ GAMEMESSAGE_SYNCH_START,
+ GAMEMESSAGE_PLAYER_OPTION,
+ GAMEMESSAGE_EXTENDED_GAME,
+ GAMEMESSAGE_AUTO_MOVES,
+ GAMEMESSAGE_TURN_COMPLETE,
+ GAMEMESSAGE_JOIN_GROUP,
+ GAMEMESSAGE_PUSH_MISSION,
+ GAMEMESSAGE_AUTO_MISSION,
+ GAMEMESSAGE_DO_COMMAND,
+ GAMEMESSAGE_PUSH_ORDER,
+ GAMEMESSAGE_POP_ORDER,
+ GAMEMESSAGE_DO_TASK,
+ GAMEMESSAGE_RESEARCH,
+ GAMEMESSAGE_PERCENT_CHANGE,
+ GAMEMESSAGE_ESPIONAGE_CHANGE,
+ GAMEMESSAGE_CONVERT,
+ GAMEMESSAGE_CHAT,
+ GAMEMESSAGE_PING,
+ GAMEMESSAGE_SIGN,
+ GAMEMESSAGE_LINE_ENTITY,
+ GAMEMESSAGE_SIGN_DELETE,
+ GAMEMESSAGE_LINE_ENTITY_DELETE,
+ GAMEMESSAGE_LINE_GROUP_DELETE,
+ GAMEMESSAGE_PAUSE,
+ GAMEMESSAGE_MP_KICK,
+ GAMEMESSAGE_MP_RETIRE,
+ GAMEMESSAGE_CLOSE_CONNECTION,
+ GAMEMESSAGE_NEVER_JOINED,
+ GAMEMESSAGE_MP_DROP_INIT,
+ GAMEMESSAGE_MP_DROP_VOTE,
+ GAMEMESSAGE_MP_DROP_UPDATE,
+ GAMEMESSAGE_MP_DROP_RESULT,
+ GAMEMESSAGE_MP_DROP_SAVE,
+ GAMEMESSAGE_TOGGLE_TRADE,
+ GAMEMESSAGE_IMPLEMENT_OFFER,
+ GAMEMESSAGE_CHANGE_WAR,
+ GAMEMESSAGE_CHANGE_VASSAL,
+ GAMEMESSAGE_CHOOSE_ELECTION,
+ GAMEMESSAGE_DIPLO_VOTE,
+ GAMEMESSAGE_APPLY_EVENT,
+ GAMEMESSAGE_CONTACT_CIV,
+ GAMEMESSAGE_DIPLO_CHAT,
+ GAMEMESSAGE_SEND_OFFER,
+ GAMEMESSAGE_DIPLO_EVENT,
+ GAMEMESSAGE_RENEGOTIATE,
+ GAMEMESSAGE_RENEGOTIATE_ITEM,
+ GAMEMESSAGE_EXIT_TRADE,
+ GAMEMESSAGE_KILL_DEAL,
+ GAMEMESSAGE_SAVE_GAME,
+ GAMEMESSAGE_UPDATE_CIVICS,
+ GAMEMESSAGE_CLEAR_TABLE,
+ GAMEMESSAGE_POPUP_PROCESSED,
+ GAMEMESSAGE_DIPLOMACY_PROCESSED,
+ GAMEMESSAGE_HOT_JOIN_NOTICE,
+ GAMEMESSAGE_HOT_DROP_NOTICE,
+ GAMEMESSAGE_DIPLOMACY,
+ GAMEMESSAGE_POPUP,
+ GAMEMESSAGE_EVENT_TRIGGERED,
+ GAMEMESSAGE_EMPIRE_SPLIT,
+ GAMEMESSAGE_LAUNCH_SPACESHIP,
+ GAMEMESSAGE_ADVANCED_START_ACTION,
+ GAMEMESSAGE_FOUND_RELIGION,
+ GAMEMESSAGE_MOD_NET_MESSAGE
+};
+
+enum PopupControlLayout // Exposed to Python
+{
+ POPUP_LAYOUT_LEFT,
+ POPUP_LAYOUT_CENTER,
+ POPUP_LAYOUT_RIGHT,
+ POPUP_LAYOUT_STRETCH,
+
+ POPUP_LAYOUT_NUMLAYOUTS
+};
+
+enum JustificationTypes // Exposed to Python
+{
+ DLL_FONT_LEFT_JUSTIFY = 1<<0,
+ DLL_FONT_RIGHT_JUSTIFY = 1<<1,
+ DLL_FONT_CENTER_JUSTIFY = 1<<2,
+ DLL_FONT_CENTER_VERTICALLY = 1<<3,
+ DLL_FONT_ADDITIVE = 1<<4,
+};
+
+enum ToolTipAlignTypes // Exposed to Python
+{
+ TOOLTIP_TOP_LEFT,
+ TOOLTIP_TOP_INLEFT,
+ TOOLTIP_TOP_CENTER,
+ TOOLTIP_TOP_INRIGHT,
+ TOOLTIP_TOP_RIGHT,
+
+ TOOLTIP_INTOP_RIGHT,
+ TOOLTIP_CENTER_RIGHT,
+ TOOLTIP_INBOTTOM_RIGHT,
+
+ TOOLTIP_BOTTOM_RIGHT,
+ TOOLTIP_BOTTOM_INRIGHT,
+ TOOLTIP_BOTTOM_CENTER,
+ TOOLTIP_BOTTOM_INLEFT,
+ TOOLTIP_BOTTOM_LEFT,
+
+ TOOLTIP_INBOTTOM_LEFT,
+ TOOLTIP_CENTER_LEFT,
+ TOOLTIP_INTOP_LEFT,
+};
+
+enum ActivationTypes // Exposed to Python
+{
+ ACTIVATE_NORMAL,
+ ACTIVATE_CHILDFOCUS,
+ ACTIVATE_MIMICPARENT,
+ ACTIVATE_MIMICPARENTFOCUS,
+};
+
+enum HitTestTypes // Exposed to Python
+{
+ HITTEST_DEFAULT,
+ HITTEST_ON,
+ HITTEST_SOLID,
+ HITTEST_CHILDREN,
+ HITTEST_NOHIT,
+};
+
+enum GraphicLevelTypes // Exposed to Python
+{
+ GRAPHICLEVEL_HIGH,
+ GRAPHICLEVEL_MEDIUM,
+ GRAPHICLEVEL_LOW,
+ GRAPHICLEVEL_CURRENT,
+
+#ifdef _USRDLL
+ NUM_GRAPHICLEVELS
+#endif
+};
+
+enum EventTypes // Exposed to Python
+{
+ NO_EVENT = -1,
+};
+
+enum EventTriggerTypes // Exposed to Python
+{
+ NO_EVENTTRIGGER = -1,
+};
+
+enum EspionageMissionTypes // Exposed to Python
+{
+ NO_ESPIONAGEMISSION = -1,
+};
+
+enum AdvancedStartActionTypes // Exposed to Python
+{
+ NO_ADVANCEDSTARTACTION = -1,
+
+ ADVANCEDSTARTACTION_EXIT,
+ ADVANCEDSTARTACTION_UNIT,
+ ADVANCEDSTARTACTION_CITY,
+ ADVANCEDSTARTACTION_POP,
+ ADVANCEDSTARTACTION_CULTURE,
+ ADVANCEDSTARTACTION_BUILDING,
+ ADVANCEDSTARTACTION_IMPROVEMENT,
+ ADVANCEDSTARTACTION_ROUTE,
+ ADVANCEDSTARTACTION_TECH,
+ ADVANCEDSTARTACTION_VISIBILITY,
+ ADVANCEDSTARTACTION_AUTOMATE
+};
+
+enum GlobeLayerTypes
+{
+ GLOBE_LAYER_STRATEGY = -1,
+ GLOBE_LAYER_TRADE,
+ GLOBE_LAYER_UNIT,
+ GLOBE_LAYER_RESOURCE,
+ GLOBE_LAYER_RELIGION,
+ GLOBE_LAYER_CULTURE,
+
+#ifdef _USRDLL
+ NUM_GLOBE_LAYER_TYPES
+#endif
+};
+
+enum GlobeLayerUnitOptionTypes
+{
+ SHOW_ALL_MILITARY,
+ SHOW_TEAM_MILITARY,
+ SHOW_ENEMIES_IN_TERRITORY,
+ SHOW_ENEMIES,
+ SHOW_PLAYER_DOMESTICS,
+
+#ifdef _USRDLL
+ NUM_UNIT_OPTION_TYPES
+#endif
+};
+
+enum GlobeLayerResourceOptionTypes
+{
+ SHOW_ALL_RESOURCES,
+ SHOW_STRATEGIC_RESOURCES,
+ SHOW_HAPPY_RESOURCES,
+ SHOW_HEALTH_RESOURCES,
+
+#ifdef _USRDLL
+ NUM_RESOURCE_OPTION_TYPES
+#endif
+};
+
+enum PlotIndicatorVisibilityFlags
+{
+ PLOT_INDICATOR_VISIBLE_ALWAYS,
+ PLOT_INDICATOR_VISIBLE_ONSCREEN_ONLY,
+ PLOT_INDICATOR_VISIBLE_OFFSCREEN_ONLY,
+ PLOT_INDICATOR_VISIBLE_ONGLOBE_ONLY,
+ PLOT_INDICATOR_VISIBLE_NEVER
+};
+
+enum UnitSubEntityTypes
+{
+ UNIT_SUB_ENTITY_NORMAL,
+ UNIT_SUB_ENTITY_LEADER,
+ UNIT_SUB_ENTITY_SIEGE_TOWER,
+ UNIT_SUB_ENTITY_COUNT
+};
+
+enum CivilopediaWidgetShowTypes
+{
+ CIVILOPEDIA_WIDGET_SHOW_NONE,
+ CIVILOPEDIA_WIDGET_SHOW_LAND,
+ CIVILOPEDIA_WIDGET_SHOW_WATER,
+};
+
+#endif // CVENUMS_h
diff --git a/CvGameCoreDLL/CvGame.cpp b/CvGameCoreDLL/CvGame.cpp
index 4572a0d..130c323 100644
--- a/CvGameCoreDLL/CvGame.cpp
+++ b/CvGameCoreDLL/CvGame.cpp
@@ -269,6 +269,9 @@ void CvGame::init(HandicapTypes eHandicap)
AI_init();
doUpdateCacheOnTurn();
+
+ // novice: Log game state when game's initialized
+ GC.getGameINLINE().logGameStateString(NO_PLAYER);
}
//
@@ -2133,31 +2136,18 @@ void CvGame::update()
//1 slice is 250 ms. Write data once per second to file
if(gDLL->IsPitbossHost() && GC.getDefineINT("ENABLE_PITBOSS_PORTAL_LOGGING") > 0) {
if ((getTurnSlice() % 4) == 0) {
-
- time_t rawtime;
- struct tm * timeinfo;
- time ( &rawtime );
- timeinfo = localtime ( &rawtime );
-
- CvString timeString = asctime (timeinfo);
- CvString from = "\n";
- CvString to = " ";
-
- replace(timeString, from, to);
-
+ // Log time.txt
CvWString turnTimerText;
getTurnTimerText(turnTimerText);
-
std::ofstream outTime(GC.getGameINLINE().getLogfilePath("time"), std::ios::trunc);
- std::ofstream outScore(GC.getGameINLINE().getLogfilePath("score"), std::ios::trunc);
outTime << (CvString)turnTimerText << "\n";
- outTime << timeString << "\n";
+ outTime << this->getLocalTimeString() << "\n";
outTime << this->getGameTurnYear() << "\n";
outTime << this->getGameTurn() << "\n";
outTime.close();
- int iCount = 0;
-
+ // Log score.txt
+ std::ofstream outScore(GC.getGameINLINE().getLogfilePath("score"), std::ios::trunc);
for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
{
CvPlayer& kPlayer = GET_PLAYER((PlayerTypes) iI);
@@ -2180,38 +2170,45 @@ void CvGame::update()
convertGameTurn << GC.getGameINLINE().getGameTurn();
outScore << " --- " << (CvString)(kPlayer.getName()) << " --- " << convertScore.str() << " --- " << convertId.str() << "\n";
+ }
+ }
+ outScore.close();
+ // Log connected, disconnected, and score change events
+ for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
+ {
+ CvPlayer& kPlayer = GET_PLAYER((PlayerTypes) iI);
+ if (kPlayer.isEverAlive())
+ {
if (kPlayer.isConnected() && (kPlayer.isConnected()!=kPlayer.getPreviousConnected())) {
kPlayer.setPreviousConnected(true);
- CvString eventText = timeString + " --- " + (CvString)(kPlayer.getName()) + " --- Connected --- ";
- eventText += convertId.str()+ " --- ";
- eventText += convertGameTurn.str() + "\n";
- appendBeginAndResize(GC.getGameINLINE().getLogfilePath("event"), eventText);
+ GC.getGameINLINE().logEvent(kPlayer.getID(), "Connected");
+ // Trigger recovery save
+ if(GC.getDefineINT("ENABLE_EXTENDED_RECOVERY_SAVES") > 0) {
+ CvString saveName = (CvString)(kPlayer.getName()) + "_connected_" + GC.getGameINLINE().getLocalTimeString(true) + ".CivBeyondSwordSave";
+ CvString fileName = GC.getGameINLINE().getLogfilePath(saveName, false);
+ gDLL->getEngineIFace()->SaveGame(fileName, SAVEGAME_RECOVERY);
+ }
}
-
- if (score!=kPlayer.getPreviousScore()) {
- kPlayer.setPreviousScore(score);
-
- CvString eventText = timeString + " --- " + (CvString)(kPlayer.getName()) + " --- ";
- eventText+= convertScore.str() + " --- " + convertId.str() + " --- ";
- eventText += convertGameTurn.str() + "\n";
- appendBeginAndResize(GC.getGameINLINE().getLogfilePath("event"), eventText);
- }
-
if (!(kPlayer.isConnected()) && (kPlayer.isConnected()!=kPlayer.getPreviousConnected())) {
kPlayer.setPreviousConnected(false);
-
- CvString eventText = timeString + " --- " + (CvString)(kPlayer.getName()) + " --- Disconnected --- ";
- eventText += convertId.str() + " --- ";
- eventText += convertGameTurn.str() + "\n";
-
- appendBeginAndResize(GC.getGameINLINE().getLogfilePath("event"), eventText);
+ GC.getGameINLINE().logEvent(kPlayer.getID(), "Disconnected");
+ // Trigger recovery save
+ if(GC.getDefineINT("ENABLE_EXTENDED_RECOVERY_SAVES") > 0) {
+ CvString saveName = (CvString)(kPlayer.getName()) + "_disconnected_" + GC.getGameINLINE().getLocalTimeString(true) + ".CivBeyondSwordSave";
+ CvString fileName = GC.getGameINLINE().getLogfilePath(saveName, false);
+ gDLL->getEngineIFace()->SaveGame(fileName, SAVEGAME_RECOVERY);
+ }
}
-
+ int score = kPlayer.calculateScore();
+ if (score!=kPlayer.getPreviousScore()) {
+ kPlayer.setPreviousScore(score);
+ std::ostringstream convertScore;
+ convertScore << score;
+ GC.getGameINLINE().logEvent(kPlayer.getID(), convertScore.str());
+ }
}
}
- outScore.close();
-
}
}
@@ -4774,6 +4771,16 @@ bool CvGame::isPaused() const
void CvGame::setPausePlayer(PlayerTypes eNewValue)
{
+ // novice: Log event for game being paused/unpaused
+ if(m_ePausePlayer != eNewValue) {
+ if(eNewValue == NO_PLAYER) {
+ GC.getGameINLINE().logEvent(eNewValue, "Game unpaused");
+ }
+ else {
+ GC.getGameINLINE().logEvent(eNewValue, "Game paused");
+ }
+ }
+
m_ePausePlayer = eNewValue;
}
@@ -5703,16 +5710,126 @@ const CvWString & CvGame::getName()
return GC.getInitCore().getGameName();
}
+// novice
+void CvGame::logEvent(PlayerTypes player, const CvString& eventType)
+{
+ if(gDLL->IsPitbossHost() && GC.getDefineINT("ENABLE_PITBOSS_PORTAL_LOGGING") > 0) {
+ CvString eventText = getLocalTimeString() + " --- ";
+ if(player == NO_PLAYER) {
+ eventText += "NO PLAYER";
+ }
+ else {
+ CvPlayer& kPlayer = GET_PLAYER(player);
+ eventText += (CvString)(kPlayer.getName());
+ }
+ eventText += " --- " + eventType + " --- ";
+
+ std::ostringstream convertPlayerId;
+ convertPlayerId << player;
+ eventText += convertPlayerId.str()+ " --- ";
+
+ std::ostringstream convertGameTurn;
+ convertGameTurn << getGameTurn();
+ eventText += convertGameTurn.str() + "\n";
+
+ appendBeginAndResize(getLogfilePath("event"), eventText);
+ }
+}
+
+// novice
+CvString CvGame::getLocalTimeString(bool removeColons)
+{
+ time_t rawtime;
+ struct tm * timeinfo;
+ time ( &rawtime );
+ timeinfo = localtime ( &rawtime );
+
+ CvString timeString = asctime (timeinfo);
+ CvString from = "\n";
+ CvString to = " ";
+
+ replace(timeString, from, to);
+
+ if(removeColons) {
+ CvString colon = ":";
+ CvString colonReplacement = "_";
+ bool found = replace(timeString, colon, colonReplacement);
+ while(found) {
+ found = replace(timeString, colon, colonReplacement);
+ }
+ CvString space = " ";
+ found = replace(timeString, space, colonReplacement);
+ while(found) {
+ found = replace(timeString, space, colonReplacement);
+ }
+ }
+
+ std::stringstream convert;
+ convert << timeString;
+ return convert.str();
+}
+
// novice - monitor
-CvString CvGame::getLogfilePath(const CvString& fileName)
+CvString CvGame::getLogfilePath(const CvString& fileName, bool addExtension)
{
std::stringstream convert;
CvString *gameName = new CvString(GC.getInitCore().getGameName().GetCString()); // Converts wide string to narrow string
- convert << GC.getDefineSTRING("PITBOSS_PORTAL_LOG_DIRECTORY") << "/" << gameName->c_str() << "_" << fileName << ".txt";
+ convert << GC.getDefineSTRING("PITBOSS_PORTAL_LOG_DIRECTORY") << "/" << gameName->c_str() << "_" << fileName;
+ if(addExtension) {
+ convert << ".txt";
+ }
delete gameName;
return convert.str();
}
+// novice - monitor
+void CvGame::logGameStateString(PlayerTypes playerEndingTurn) {
+ if(gDLL->IsPitbossHost() && GC.getDefineINT("ENABLE_PITBOSS_PORTAL_GAMESTATE_LOGGING") > 0) {
+ std::stringstream filename;
+ filename << "gamestate_";
+ std::ostringstream convertGameTurn;
+ convertGameTurn << getGameTurn();
+
+ if(playerEndingTurn == NO_PLAYER) {
+ filename << "sot" << convertGameTurn.str();
+ }
+ else {
+ filename << "eot" << convertGameTurn.str() << "_player";
+ std::ostringstream convertPlayerId;
+ convertPlayerId << playerEndingTurn;
+ filename << convertPlayerId.str();
+ }
+ std::ofstream outState(getLogfilePath(filename.str()), std::ios::trunc);
+ outState << getGameStateString() << "\n";
+ outState.close();
+ }
+}
+
+// novice - monitor/observer. Call into python function getGameStateString in file CvGameInterface.py to get a string representation of the current game state
+CvString CvGame::getGameStateString()
+{
+ try
+ {
+ CvWStringBuffer szBuffer;
+ CvWString szGameState;
+ CyArgsList argsList;
+ argsList.add(0);
+ gDLL->getPythonIFace()->callFunction(PYGameModule, "getGameStateString", argsList.makeFunctionArgs(), &szGameState);
+ szBuffer.append(szGameState);
+ std::wstring gameState = szBuffer.getCString();
+ CvString *gameStateN = new CvString(gameState);
+ std::stringstream convert;
+ convert << gameStateN->c_str();
+ delete gameStateN;
+ return convert.str();
+ }
+ catch(std::exception & e) {
+ std::stringstream ex;
+ ex << "{ \"error\": \"Error getting game state from python: " << e.what() << "\"}";
+ return ex.str();
+ }
+}
+
void CvGame::setName(const TCHAR* szName)
{
GC.getInitCore().setGameName(szName);
@@ -5889,11 +6006,9 @@ void CvGame::doTurn()
gDLL->getEngineIFace()->AutoSave();
// novice - monitor: Log game state at start of turn
- if(gDLL->IsPitbossHost() && GC.getDefineINT("ENABLE_PITBOSS_PORTAL_LOGGING") > 0) {
- std::ostringstream convertGameTurn;
- convertGameTurn << GC.getGameINLINE().getGameTurn();
- GC.getGameINLINE().appendBeginAndResize(GC.getGameINLINE().getLogfilePath("gamestate_sot" + convertGameTurn.str()), "State of game: Start of turn " + convertGameTurn.str());
- }
+ GC.getGameINLINE().logGameStateString(NO_PLAYER);
+ // novice: Log event when turn starts so that the turn roll is immediately recorded
+ GC.getGameINLINE().logEvent(NO_PLAYER, "New turn");
}
diff --git a/CvGameCoreDLL/CvGame.h b/CvGameCoreDLL/CvGame.h
index 23b04eb..e3083f0 100644
--- a/CvGameCoreDLL/CvGame.h
+++ b/CvGameCoreDLL/CvGame.h
@@ -548,7 +548,15 @@ class CvGame
void appendBeginAndResize(CvString filepath, CvString inputData);
bool replace(CvString& str, const CvString& from, CvString& to);
// novice - monitor
- CvString getLogfilePath(const CvString& fileName);
+ CvString getLogfilePath(const CvString& fileName, bool addExtension = true);
+ // novice - monitor
+ CvString CvGame::getGameStateString();
+ // novice - monitor
+ void CvGame::logGameStateString(PlayerTypes playerEndingTurn);
+ // novice
+ void CvGame::logEvent(PlayerTypes player, const CvString& eventType);
+ // novice
+ CvString CvGame::getLocalTimeString(bool removeColons = false);
protected:
int m_iElapsedGameTurns;
@@ -693,7 +701,8 @@ class CvGame
CvPlot* normalizeFindLakePlot(PlayerTypes ePlayer);
void doUpdateCacheOnTurn();
- //Plako for Rbmod (monitor)
+
+ //Plako for Rbmod (monitor)
void getTurnTimerText(CvWString& strText);
};
diff --git a/CvGameCoreDLL/CvGameTextMgr.cpp b/CvGameCoreDLL/CvGameTextMgr.cpp
new file mode 100644
index 0000000..9f165c1
--- /dev/null
+++ b/CvGameCoreDLL/CvGameTextMgr.cpp
@@ -0,0 +1,14805 @@
+//---------------------------------------------------------------------------------------
+//
+// ***************** Civilization IV ********************
+//
+// FILE: CvGameTextMgr.cpp
+//
+// PURPOSE: Interfaces with GameText XML Files to manage the paths of art files
+//
+//---------------------------------------------------------------------------------------
+// Copyright (c) 2004 Firaxis Games, Inc. All rights reserved.
+//---------------------------------------------------------------------------------------
+
+#include "CvGameCoreDLL.h"
+#include "CvGameTextMgr.h"
+#include "CvGameCoreUtils.h"
+#include "CvDLLUtilityIFaceBase.h"
+#include "CvDLLInterfaceIFaceBase.h"
+#include "CvDLLSymbolIFaceBase.h"
+#include "CvInfos.h"
+#include "CvXMLLoadUtility.h"
+#include "CvCity.h"
+#include "CvPlayerAI.h"
+#include "CvTeamAI.h"
+#include "CvGameAI.h"
+#include "CvSelectionGroup.h"
+#include "CvMap.h"
+#include "CvArea.h"
+#include "CvPlot.h"
+#include "CvPopupInfo.h"
+#include "FProfiler.h"
+#include "CyArgsList.h"
+#include "CvDLLPythonIFaceBase.h"
+
+int shortenID(int iId)
+{
+ return iId;
+}
+
+// For displaying Asserts and error messages
+static char* szErrorMsg;
+
+//----------------------------------------------------------------------------
+//
+// FUNCTION: GetInstance()
+//
+// PURPOSE: Get the instance of this class.
+//
+//----------------------------------------------------------------------------
+CvGameTextMgr& CvGameTextMgr::GetInstance()
+{
+ static CvGameTextMgr gs_GameTextMgr;
+ return gs_GameTextMgr;
+}
+
+//----------------------------------------------------------------------------
+//
+// FUNCTION: CvGameTextMgr()
+//
+// PURPOSE: Constructor
+//
+//----------------------------------------------------------------------------
+CvGameTextMgr::CvGameTextMgr()
+{
+
+}
+
+CvGameTextMgr::~CvGameTextMgr()
+{
+}
+
+//----------------------------------------------------------------------------
+//
+// FUNCTION: Initialize()
+//
+// PURPOSE: Allocates memory
+//
+//----------------------------------------------------------------------------
+void CvGameTextMgr::Initialize()
+{
+
+}
+
+//----------------------------------------------------------------------------
+//
+// FUNCTION: DeInitialize()
+//
+// PURPOSE: Clears memory
+//
+//----------------------------------------------------------------------------
+void CvGameTextMgr::DeInitialize()
+{
+ for(int i=0;i<(int)m_apbPromotion.size();i++)
+ {
+ delete [] m_apbPromotion[i];
+ }
+}
+
+//----------------------------------------------------------------------------
+//
+// FUNCTION: Reset()
+//
+// PURPOSE: Accesses CvXMLLoadUtility to clean global text memory and
+// reload the XML files
+//
+//----------------------------------------------------------------------------
+void CvGameTextMgr::Reset()
+{
+ CvXMLLoadUtility pXML;
+ pXML.LoadGlobalText();
+}
+
+
+// Returns the current language
+int CvGameTextMgr::getCurrentLanguage()
+{
+ return gDLL->getCurrentLanguage();
+}
+
+void CvGameTextMgr::setYearStr(CvWString& szString, int iGameTurn, bool bSave, CalendarTypes eCalendar, int iStartYear, GameSpeedTypes eSpeed)
+{
+ int iTurnYear = getTurnYearForGame(iGameTurn, iStartYear, eCalendar, eSpeed);
+
+ if (iTurnYear < 0)
+ {
+ if (bSave)
+ {
+ szString = gDLL->getText("TXT_KEY_TIME_BC_SAVE", CvWString::format(L"%04d", -iTurnYear).GetCString());
+ }
+ else
+ {
+ szString = gDLL->getText("TXT_KEY_TIME_BC", -(iTurnYear));
+ }
+ }
+ else if (iTurnYear > 0)
+ {
+ if (bSave)
+ {
+ szString = gDLL->getText("TXT_KEY_TIME_AD_SAVE", CvWString::format(L"%04d", iTurnYear).GetCString());
+ }
+ else
+ {
+ szString = gDLL->getText("TXT_KEY_TIME_AD", iTurnYear);
+ }
+ }
+ else
+ {
+ if (bSave)
+ {
+ szString = gDLL->getText("TXT_KEY_TIME_AD_SAVE", L"0001");
+ }
+ else
+ {
+ szString = gDLL->getText("TXT_KEY_TIME_AD", 1);
+ }
+ }
+}
+
+
+void CvGameTextMgr::setDateStr(CvWString& szString, int iGameTurn, bool bSave, CalendarTypes eCalendar, int iStartYear, GameSpeedTypes eSpeed)
+{
+ CvWString szYearBuffer;
+ CvWString szWeekBuffer;
+
+ setYearStr(szYearBuffer, iGameTurn, bSave, eCalendar, iStartYear, eSpeed);
+
+ switch (eCalendar)
+ {
+ case CALENDAR_DEFAULT:
+ if (0 == (getTurnMonthForGame(iGameTurn + 1, iStartYear, eCalendar, eSpeed) - getTurnMonthForGame(iGameTurn, iStartYear, eCalendar, eSpeed)) % GC.getNumMonthInfos())
+ {
+ szString = szYearBuffer;
+ }
+ else
+ {
+ int iMonth = getTurnMonthForGame(iGameTurn, iStartYear, eCalendar, eSpeed);
+ if (bSave)
+ {
+ szString = (szYearBuffer + "-" + GC.getMonthInfo((MonthTypes)(iMonth % GC.getNumMonthInfos())).getDescription());
+ }
+ else
+ {
+ szString = (GC.getMonthInfo((MonthTypes)(iMonth % GC.getNumMonthInfos())).getDescription() + CvString(", ") + szYearBuffer);
+ }
+ }
+ break;
+ case CALENDAR_YEARS:
+ case CALENDAR_BI_YEARLY:
+ szString = szYearBuffer;
+ break;
+
+ case CALENDAR_TURNS:
+ szString = gDLL->getText("TXT_KEY_TIME_TURN", (iGameTurn + 1));
+ break;
+
+ case CALENDAR_SEASONS:
+ if (bSave)
+ {
+ szString = (szYearBuffer + "-" + GC.getSeasonInfo((SeasonTypes)(iGameTurn % GC.getNumSeasonInfos())).getDescription());
+ }
+ else
+ {
+ szString = (GC.getSeasonInfo((SeasonTypes)(iGameTurn % GC.getNumSeasonInfos())).getDescription() + CvString(", ") + szYearBuffer);
+ }
+ break;
+
+ case CALENDAR_MONTHS:
+ if (bSave)
+ {
+ szString = (szYearBuffer + "-" + GC.getMonthInfo((MonthTypes)(iGameTurn % GC.getNumMonthInfos())).getDescription());
+ }
+ else
+ {
+ szString = (GC.getMonthInfo((MonthTypes)(iGameTurn % GC.getNumMonthInfos())).getDescription() + CvString(", ") + szYearBuffer);
+ }
+ break;
+
+ case CALENDAR_WEEKS:
+ szWeekBuffer = gDLL->getText("TXT_KEY_TIME_WEEK", ((iGameTurn % GC.getDefineINT("WEEKS_PER_MONTHS")) + 1));
+
+ if (bSave)
+ {
+ szString = (szYearBuffer + "-" + GC.getMonthInfo((MonthTypes)((iGameTurn / GC.getDefineINT("WEEKS_PER_MONTHS")) % GC.getNumMonthInfos())).getDescription() + "-" + szWeekBuffer);
+ }
+ else
+ {
+ szString = (szWeekBuffer + ", " + GC.getMonthInfo((MonthTypes)((iGameTurn / GC.getDefineINT("WEEKS_PER_MONTHS")) % GC.getNumMonthInfos())).getDescription() + ", " + szYearBuffer);
+ }
+ break;
+
+ default:
+ FAssert(false);
+ }
+}
+
+
+void CvGameTextMgr::setTimeStr(CvWString& szString, int iGameTurn, bool bSave)
+{
+ setDateStr(szString, iGameTurn, bSave, GC.getGameINLINE().getCalendar(), GC.getGameINLINE().getStartYear(), GC.getGameINLINE().getGameSpeedType());
+}
+
+
+void CvGameTextMgr::setInterfaceTime(CvWString& szString, PlayerTypes ePlayer)
+{
+ CvWString szTempBuffer;
+
+ if (GET_PLAYER(ePlayer).isGoldenAge())
+ {
+ szString.Format(L"%c(%d) ", gDLL->getSymbolID(GOLDEN_AGE_CHAR), GET_PLAYER(ePlayer).getGoldenAgeTurns());
+ }
+ else
+ {
+ szString.clear();
+ }
+
+ setTimeStr(szTempBuffer, GC.getGameINLINE().getGameTurn(), false);
+ szString += CvWString(szTempBuffer);
+}
+
+
+void CvGameTextMgr::setGoldStr(CvWString& szString, PlayerTypes ePlayer)
+{
+ if (GET_PLAYER(ePlayer).getGold() < 0)
+ {
+ szString.Format(L"%c: " SETCOLR L"%d" SETCOLR, GC.getCommerceInfo(COMMERCE_GOLD).getChar(), TEXT_COLOR("COLOR_NEGATIVE_TEXT"), GET_PLAYER(ePlayer).getGold());
+ }
+ else
+ {
+ szString.Format(L"%c: %d", GC.getCommerceInfo(COMMERCE_GOLD).getChar(), GET_PLAYER(ePlayer).getGold());
+ }
+
+ int iGoldRate = GET_PLAYER(ePlayer).calculateGoldRate();
+ if (iGoldRate < 0)
+ {
+ szString += gDLL->getText("TXT_KEY_MISC_NEG_GOLD_PER_TURN", iGoldRate);
+ }
+ else if (iGoldRate > 0)
+ {
+ szString += gDLL->getText("TXT_KEY_MISC_POS_GOLD_PER_TURN", iGoldRate);
+ }
+
+ if (GET_PLAYER(ePlayer).isStrike())
+ {
+ szString += gDLL->getText("TXT_KEY_MISC_STRIKE");
+ }
+}
+
+
+void CvGameTextMgr::setResearchStr(CvWString& szString, PlayerTypes ePlayer)
+{
+ CvWString szTempBuffer;
+
+ szString = gDLL->getText("TXT_KEY_MISC_RESEARCH_STRING", GC.getTechInfo(GET_PLAYER(ePlayer).getCurrentResearch()).getTextKeyWide());
+
+ if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getTechCount(GET_PLAYER(ePlayer).getCurrentResearch()) > 0)
+ {
+ szTempBuffer.Format(L" %d", (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getTechCount(GET_PLAYER(ePlayer).getCurrentResearch()) + 1));
+ szString+=szTempBuffer;
+ }
+
+ szTempBuffer.Format(L" (%d)", GET_PLAYER(ePlayer).getResearchTurnsLeft(GET_PLAYER(ePlayer).getCurrentResearch(), true));
+ szString+=szTempBuffer;
+}
+
+
+void CvGameTextMgr::setOOSSeeds(CvWString& szString, PlayerTypes ePlayer)
+{
+ if (GET_PLAYER(ePlayer).isHuman())
+ {
+ int iNetID = GET_PLAYER(ePlayer).getNetID();
+ if (gDLL->isConnected(iNetID))
+ {
+ szString = gDLL->getText("TXT_KEY_PLAYER_OOS", gDLL->GetSyncOOS(iNetID), gDLL->GetOptionsOOS(iNetID));
+ }
+ }
+}
+
+void CvGameTextMgr::setNetStats(CvWString& szString, PlayerTypes ePlayer)
+{
+ if (ePlayer != GC.getGameINLINE().getActivePlayer())
+ {
+ if (GET_PLAYER(ePlayer).isHuman())
+ {
+ if (gDLL->getInterfaceIFace()->isNetStatsVisible())
+ {
+ int iNetID = GET_PLAYER(ePlayer).getNetID();
+ if (gDLL->isConnected(iNetID))
+ {
+ szString = gDLL->getText("TXT_KEY_MISC_NUM_MS", gDLL->GetLastPing(iNetID));
+ }
+ else
+ {
+ szString = gDLL->getText("TXT_KEY_MISC_DISCONNECTED");
+ }
+ }
+ }
+ else
+ {
+ szString = gDLL->getText("TXT_KEY_MISC_AI");
+ }
+ }
+}
+
+
+void CvGameTextMgr::setMinimizePopupHelp(CvWString& szString, const CvPopupInfo & info)
+{
+ CvCity* pCity;
+ UnitTypes eTrainUnit;
+ BuildingTypes eConstructBuilding;
+ ProjectTypes eCreateProject;
+ ReligionTypes eReligion;
+ CivicTypes eCivic;
+
+ switch (info.getButtonPopupType())
+ {
+ case BUTTONPOPUP_CHOOSEPRODUCTION:
+ pCity = GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getCity(info.getData1());
+ if (pCity != NULL)
+ {
+ eTrainUnit = NO_UNIT;
+ eConstructBuilding = NO_BUILDING;
+ eCreateProject = NO_PROJECT;
+
+ switch (info.getData2())
+ {
+ case (ORDER_TRAIN):
+ eTrainUnit = (UnitTypes)info.getData3();
+ break;
+ case (ORDER_CONSTRUCT):
+ eConstructBuilding = (BuildingTypes)info.getData3();
+ break;
+ case (ORDER_CREATE):
+ eCreateProject = (ProjectTypes)info.getData3();
+ break;
+ default:
+ break;
+ }
+
+ if (eTrainUnit != NO_UNIT)
+ {
+ szString += gDLL->getText("TXT_KEY_MINIMIZED_CHOOSE_PRODUCTION_UNIT", GC.getUnitInfo(eTrainUnit).getTextKeyWide(), pCity->getNameKey());
+ }
+ else if (eConstructBuilding != NO_BUILDING)
+ {
+ szString += gDLL->getText("TXT_KEY_MINIMIZED_CHOOSE_PRODUCTION_BUILDING", GC.getBuildingInfo(eConstructBuilding).getTextKeyWide(), pCity->getNameKey());
+ }
+ else if (eCreateProject != NO_PROJECT)
+ {
+ szString += gDLL->getText("TXT_KEY_MINIMIZED_CHOOSE_PRODUCTION_PROJECT", GC.getProjectInfo(eCreateProject).getTextKeyWide(), pCity->getNameKey());
+ }
+ else
+ {
+ szString += gDLL->getText("TXT_KEY_MINIMIZED_CHOOSE_PRODUCTION", pCity->getNameKey());
+ }
+ }
+ break;
+
+ case BUTTONPOPUP_CHANGERELIGION:
+ eReligion = ((ReligionTypes)(info.getData1()));
+ if (eReligion != NO_RELIGION)
+ {
+ szString += gDLL->getText("TXT_KEY_MINIMIZED_CHANGE_RELIGION", GC.getReligionInfo(eReligion).getTextKeyWide());
+ }
+ break;
+
+ case BUTTONPOPUP_CHOOSETECH:
+ if (info.getData1() > 0)
+ {
+ szString += gDLL->getText("TXT_KEY_MINIMIZED_CHOOSE_TECH_FREE");
+ }
+ else
+ {
+ szString += gDLL->getText("TXT_KEY_MINIMIZED_CHOOSE_TECH");
+ }
+ break;
+
+ case BUTTONPOPUP_CHANGECIVIC:
+ eCivic = ((CivicTypes)(info.getData2()));
+ if (eCivic != NO_CIVIC)
+ {
+ szString += gDLL->getText("TXT_KEY_MINIMIZED_CHANGE_CIVIC", GC.getCivicInfo(eCivic).getTextKeyWide());
+ }
+ break;
+ }
+}
+
+void CvGameTextMgr::setEspionageMissionHelp(CvWStringBuffer &szBuffer, const CvUnit* pUnit)
+{
+ if (pUnit->isSpy())
+ {
+ PlayerTypes eOwner = pUnit->plot()->getOwnerINLINE();
+ if (NO_PLAYER != eOwner && GET_PLAYER(eOwner).getTeam() != pUnit->getTeam())
+ {
+ if (!pUnit->canEspionage(pUnit->plot()))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_HELP_NO_ESPIONAGE"));
+
+ if (pUnit->hasMoved() || pUnit->isMadeAttack())
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_HELP_NO_ESPIONAGE_REASON_MOVED"));
+ }
+ else if (!pUnit->isInvisible(GET_PLAYER(eOwner).getTeam(), false))
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_HELP_NO_ESPIONAGE_REASON_VISIBLE", GET_PLAYER(eOwner).getNameKey()));
+ }
+ }
+ else if (pUnit->getFortifyTurns() > 0)
+ {
+ int iModifier = -(pUnit->getFortifyTurns() * GC.getDefineINT("ESPIONAGE_EACH_TURN_UNIT_COST_DECREASE"));
+ if (0 != iModifier)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_COST", iModifier));
+ }
+ }
+ }
+ }
+}
+
+
+void CvGameTextMgr::setUnitHelp(CvWStringBuffer &szString, const CvUnit* pUnit, bool bOneLine, bool bShort)
+{
+ PROFILE_FUNC();
+
+ CvWString szTempBuffer;
+ BuildTypes eBuild;
+ int iCurrMoves;
+ int iI;
+ bool bFirst;
+ bool bShift = gDLL->shiftKey();
+ bool bAlt = gDLL->altKey();
+
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR("COLOR_UNIT_TEXT"), pUnit->getName().GetCString());
+ szString.append(szTempBuffer);
+
+ szString.append(L", ");
+
+ if (pUnit->getDomainType() == DOMAIN_AIR)
+ {
+ if (pUnit->airBaseCombatStr() > 0)
+ {
+ if (pUnit->isFighting())
+ {
+ szTempBuffer.Format(L"?/%d%c, ", pUnit->airBaseCombatStr(), gDLL->getSymbolID(STRENGTH_CHAR));
+ }
+ else if (pUnit->isHurt())
+ {
+ szTempBuffer.Format(L"%.1f/%d%c, ", (((float)(pUnit->airBaseCombatStr() * pUnit->currHitPoints())) / ((float)(pUnit->maxHitPoints()))), pUnit->airBaseCombatStr(), gDLL->getSymbolID(STRENGTH_CHAR));
+ }
+ else
+ {
+ szTempBuffer.Format(L"%d%c, ", pUnit->airBaseCombatStr(), gDLL->getSymbolID(STRENGTH_CHAR));
+ }
+ szString.append(szTempBuffer);
+ }
+ }
+ else
+ {
+ if (pUnit->canFight())
+ {
+ if (pUnit->isFighting())
+ {
+ szTempBuffer.Format(L"?/%d%c, ", pUnit->baseCombatStr(), gDLL->getSymbolID(STRENGTH_CHAR));
+ }
+ else if (pUnit->isHurt())
+ {
+ szTempBuffer.Format(L"%.1f/%d%c, ", (((float)(pUnit->baseCombatStr() * pUnit->currHitPoints())) / ((float)(pUnit->maxHitPoints()))), pUnit->baseCombatStr(), gDLL->getSymbolID(STRENGTH_CHAR));
+ }
+ else
+ {
+ szTempBuffer.Format(L"%d%c, ", pUnit->baseCombatStr(), gDLL->getSymbolID(STRENGTH_CHAR));
+ }
+ szString.append(szTempBuffer);
+ }
+ }
+
+ iCurrMoves = ((pUnit->movesLeft() / GC.getMOVE_DENOMINATOR()) + (((pUnit->movesLeft() % GC.getMOVE_DENOMINATOR()) > 0) ? 1 : 0));
+ if ((pUnit->baseMoves() == iCurrMoves) || (pUnit->getTeam() != GC.getGameINLINE().getActiveTeam()))
+ {
+ szTempBuffer.Format(L"%d%c", pUnit->baseMoves(), gDLL->getSymbolID(MOVES_CHAR));
+ }
+ else
+ {
+ szTempBuffer.Format(L"%d/%d%c", iCurrMoves, pUnit->baseMoves(), gDLL->getSymbolID(MOVES_CHAR));
+ }
+ szString.append(szTempBuffer);
+
+ if (pUnit->airRange() > 0)
+ {
+ szString.append(gDLL->getText("TXT_KEY_UNIT_HELP_AIR_RANGE", pUnit->airRange()));
+ }
+
+ eBuild = pUnit->getBuildType();
+
+ if (eBuild != NO_BUILD)
+ {
+ szString.append(L", ");
+ szTempBuffer.Format(L"%s (%d)", GC.getBuildInfo(eBuild).getDescription(), pUnit->plot()->getBuildTurnsLeft(eBuild, 0, 0));
+ szString.append(szTempBuffer);
+ }
+
+ if (pUnit->getImmobileTimer() > 0)
+ {
+ szString.append(L", ");
+ szString.append(gDLL->getText("TXT_KEY_UNIT_HELP_IMMOBILE", pUnit->getImmobileTimer()));
+ }
+
+ /*if (!bOneLine)
+ {
+ if (pUnit->getUnitCombatType() != NO_UNITCOMBAT)
+ {
+ szTempBuffer.Format(L" (%s)", GC.getUnitCombatInfo(pUnit->getUnitCombatType()).getDescription());
+ szString += szTempBuffer;
+ }
+ }*/
+
+ if (GC.getGameINLINE().isDebugMode() && !bAlt && !bShift)
+ {
+ FAssertMsg(pUnit->AI_getUnitAIType() != NO_UNITAI, "pUnit's AI type expected to != NO_UNITAI");
+ szTempBuffer.Format(L" (%s)", GC.getUnitAIInfo(pUnit->AI_getUnitAIType()).getDescription());
+ szString.append(szTempBuffer);
+ }
+
+ if ((pUnit->getTeam() == GC.getGameINLINE().getActiveTeam()) || GC.getGameINLINE().isDebugMode())
+ {
+ if ((pUnit->getExperience() > 0) && !(pUnit->isFighting()))
+ {
+ szString.append(gDLL->getText("TXT_KEY_UNIT_HELP_LEVEL", pUnit->getExperience(), pUnit->experienceNeeded()));
+ }
+ }
+
+ if (pUnit->getOwnerINLINE() != GC.getGameINLINE().getActivePlayer() && !pUnit->isAnimal() && !pUnit->getUnitInfo().isHiddenNationality())
+ {
+ szString.append(L", ");
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, GET_PLAYER(pUnit->getOwnerINLINE()).getPlayerTextColorR(), GET_PLAYER(pUnit->getOwnerINLINE()).getPlayerTextColorG(), GET_PLAYER(pUnit->getOwnerINLINE()).getPlayerTextColorB(), GET_PLAYER(pUnit->getOwnerINLINE()).getPlayerTextColorA(), GET_PLAYER(pUnit->getOwnerINLINE()).getName());
+ szString.append(szTempBuffer);
+ }
+
+ for (iI = 0; iI < GC.getNumPromotionInfos(); ++iI)
+ {
+ if (pUnit->isHasPromotion((PromotionTypes)iI))
+ {
+ szTempBuffer.Format(L"
", GC.getPromotionInfo((PromotionTypes)iI).getButton());
+ szString.append(szTempBuffer);
+ }
+ }
+ if (bAlt && (gDLL->getChtLvl() > 0))
+ {
+ CvSelectionGroup* eGroup = pUnit->getGroup();
+ if (eGroup != NULL)
+ {
+ if (pUnit->isGroupHead())
+ szString.append(CvWString::format(L"\nLeading "));
+ else
+ szString.append(L"\n");
+
+ szTempBuffer.Format(L"Group(%d), %d units", eGroup->getID(), eGroup->getNumUnits());
+ szString.append(szTempBuffer);
+ }
+ }
+
+ if (!bOneLine)
+ {
+ setEspionageMissionHelp(szString, pUnit);
+
+ if (pUnit->cargoSpace() > 0)
+ {
+ if (pUnit->getTeam() == GC.getGameINLINE().getActiveTeam())
+ {
+ szTempBuffer = NEWLINE + gDLL->getText("TXT_KEY_UNIT_HELP_CARGO_SPACE", pUnit->getCargo(), pUnit->cargoSpace());
+ }
+ else
+ {
+ szTempBuffer = NEWLINE + gDLL->getText("TXT_KEY_UNIT_CARGO_SPACE", pUnit->cargoSpace());
+ }
+ szString.append(szTempBuffer);
+
+ if (pUnit->specialCargo() != NO_SPECIALUNIT)
+ {
+ szString.append(gDLL->getText("TXT_KEY_UNIT_CARRIES", GC.getSpecialUnitInfo(pUnit->specialCargo()).getTextKeyWide()));
+ }
+ }
+
+ if (pUnit->fortifyModifier() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_HELP_FORTIFY_BONUS", pUnit->fortifyModifier()));
+ }
+
+ if (!bShort)
+ {
+ if (pUnit->nukeRange() >= 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_CAN_NUKE"));
+ }
+
+ if (pUnit->alwaysInvisible())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_INVISIBLE_ALL"));
+ }
+ else if (pUnit->getInvisibleType() != NO_INVISIBLE)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_INVISIBLE_MOST"));
+ }
+
+ for (iI = 0; iI < pUnit->getNumSeeInvisibleTypes(); ++iI)
+ {
+ if (pUnit->getSeeInvisibleType(iI) != pUnit->getInvisibleType())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_SEE_INVISIBLE", GC.getInvisibleInfo(pUnit->getSeeInvisibleType(iI)).getTextKeyWide()));
+ }
+ }
+
+ if (pUnit->canMoveImpassable())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_CAN_MOVE_IMPASSABLE"));
+ }
+ }
+
+ if (pUnit->maxFirstStrikes() > 0)
+ {
+ if (pUnit->firstStrikes() == pUnit->maxFirstStrikes())
+ {
+ if (pUnit->firstStrikes() == 1)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_ONE_FIRST_STRIKE"));
+ }
+ else
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_NUM_FIRST_STRIKES", pUnit->firstStrikes()));
+ }
+ }
+ else
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_FIRST_STRIKE_CHANCES", pUnit->firstStrikes(), pUnit->maxFirstStrikes()));
+ }
+ }
+
+ if (pUnit->immuneToFirstStrikes())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_IMMUNE_FIRST_STRIKES"));
+ }
+
+ if (!bShort)
+ {
+ if (pUnit->noDefensiveBonus())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_NO_DEFENSE_BONUSES"));
+ }
+
+ if (pUnit->flatMovementCost())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_FLAT_MOVEMENT"));
+ }
+
+ if (pUnit->ignoreTerrainCost())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_IGNORE_TERRAIN"));
+ }
+
+ if (pUnit->isBlitz())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_BLITZ_TEXT"));
+ }
+
+ if (pUnit->isAmphib())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_AMPHIB_TEXT"));
+ }
+
+ if (pUnit->isRiver())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_RIVER_ATTACK_TEXT"));
+ }
+
+ if (pUnit->isEnemyRoute())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_ENEMY_ROADS_TEXT"));
+ }
+
+ if (pUnit->isAlwaysHeal())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_ALWAYS_HEAL_TEXT"));
+ }
+
+ if (pUnit->isHillsDoubleMove())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_HILLS_MOVE_TEXT"));
+ }
+
+ for (iI = 0; iI < GC.getNumTerrainInfos(); ++iI)
+ {
+ if (pUnit->isTerrainDoubleMove((TerrainTypes)iI))
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_DOUBLE_MOVE_TEXT", GC.getTerrainInfo((TerrainTypes) iI).getTextKeyWide()));
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumFeatureInfos(); ++iI)
+ {
+ if (pUnit->isFeatureDoubleMove((FeatureTypes)iI))
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_DOUBLE_MOVE_TEXT", GC.getFeatureInfo((FeatureTypes) iI).getTextKeyWide()));
+ }
+ }
+
+ if (pUnit->getExtraVisibilityRange() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_VISIBILITY_TEXT", pUnit->getExtraVisibilityRange()));
+ }
+
+ if (pUnit->getExtraMoveDiscount() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_MOVE_DISCOUNT_TEXT", -(pUnit->getExtraMoveDiscount())));
+ }
+
+ if (pUnit->getExtraEnemyHeal() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_HEALS_EXTRA_TEXT", pUnit->getExtraEnemyHeal()) + gDLL->getText("TXT_KEY_PROMOTION_ENEMY_LANDS_TEXT"));
+ }
+
+ if (pUnit->getExtraNeutralHeal() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_HEALS_EXTRA_TEXT", pUnit->getExtraNeutralHeal()) + gDLL->getText("TXT_KEY_PROMOTION_NEUTRAL_LANDS_TEXT"));
+ }
+
+ if (pUnit->getExtraFriendlyHeal() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_HEALS_EXTRA_TEXT", pUnit->getExtraFriendlyHeal()) + gDLL->getText("TXT_KEY_PROMOTION_FRIENDLY_LANDS_TEXT"));
+ }
+
+ if (pUnit->getSameTileHeal() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_HEALS_SAME_TEXT", pUnit->getSameTileHeal()) + gDLL->getText("TXT_KEY_PROMOTION_DAMAGE_TURN_TEXT"));
+ }
+
+ if (pUnit->getAdjacentTileHeal() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_HEALS_ADJACENT_TEXT", pUnit->getAdjacentTileHeal()) + gDLL->getText("TXT_KEY_PROMOTION_DAMAGE_TURN_TEXT"));
+ }
+ }
+
+ if (pUnit->currInterceptionProbability() > 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_INTERCEPT_AIRCRAFT", pUnit->currInterceptionProbability()));
+ }
+
+ if (pUnit->evasionProbability() > 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_EVADE_INTERCEPTION", pUnit->evasionProbability()));
+ }
+
+ if (pUnit->withdrawalProbability() > 0)
+ {
+ if (bShort)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_WITHDRAWL_PROBABILITY_SHORT", pUnit->withdrawalProbability()));
+ }
+ else
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_WITHDRAWL_PROBABILITY", pUnit->withdrawalProbability()));
+ }
+ }
+
+ if (pUnit->combatLimit() < GC.getMAX_HIT_POINTS() && pUnit->canAttack())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_COMBAT_LIMIT", (100 * pUnit->combatLimit()) / GC.getMAX_HIT_POINTS()));
+ }
+
+ if (pUnit->collateralDamage() > 0)
+ {
+ szString.append(NEWLINE);
+ if (pUnit->getExtraCollateralDamage() == 0)
+ {
+ szString.append(gDLL->getText("TXT_KEY_UNIT_COLLATERAL_DAMAGE", ( 100 * pUnit->getUnitInfo().getCollateralDamageLimit() / GC.getMAX_HIT_POINTS())));
+ }
+ else
+ {
+ szString.append(gDLL->getText("TXT_KEY_UNIT_COLLATERAL_DAMAGE_EXTRA", pUnit->getExtraCollateralDamage()));
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); ++iI)
+ {
+ if (pUnit->getUnitInfo().getUnitCombatCollateralImmune(iI))
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_COLLATERAL_IMMUNE", GC.getUnitCombatInfo((UnitCombatTypes)iI).getTextKeyWide()));
+ }
+ }
+
+ if (pUnit->getCollateralDamageProtection() > 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_COLLATERAL_PROTECTION_TEXT", pUnit->getCollateralDamageProtection()));
+ }
+
+ if (pUnit->getExtraCombatPercent() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_STRENGTH_TEXT", pUnit->getExtraCombatPercent()));
+ }
+
+ if (pUnit->cityAttackModifier() == pUnit->cityDefenseModifier())
+ {
+ if (pUnit->cityAttackModifier() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_CITY_STRENGTH_MOD", pUnit->cityAttackModifier()));
+ }
+ }
+ else
+ {
+ if (pUnit->cityAttackModifier() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_CITY_ATTACK_TEXT", pUnit->cityAttackModifier()));
+ }
+
+ if (pUnit->cityDefenseModifier() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PROMOTION_CITY_DEFENSE_TEXT", pUnit->cityDefenseModifier()));
+ }
+ }
+
+ if (pUnit->animalCombatModifier() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_ANIMAL_COMBAT_MOD", pUnit->animalCombatModifier()));
+ }
+
+ if (pUnit->getDropRange() > 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_PARADROP_RANGE", pUnit->getDropRange()));
+ }
+
+ if (pUnit->hillsAttackModifier() == pUnit->hillsDefenseModifier())
+ {
+ if (pUnit->hillsAttackModifier() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_HILLS_STRENGTH", pUnit->hillsAttackModifier()));
+ }
+ }
+ else
+ {
+ if (pUnit->hillsAttackModifier() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_HILLS_ATTACK", pUnit->hillsAttackModifier()));
+ }
+
+ if (pUnit->hillsDefenseModifier() != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_HILLS_DEFENSE", pUnit->hillsDefenseModifier()));
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumTerrainInfos(); ++iI)
+ {
+ if (pUnit->terrainAttackModifier((TerrainTypes)iI) == pUnit->terrainDefenseModifier((TerrainTypes)iI))
+ {
+ if (pUnit->terrainAttackModifier((TerrainTypes)iI) != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_STRENGTH", pUnit->terrainAttackModifier((TerrainTypes)iI), GC.getTerrainInfo((TerrainTypes) iI).getTextKeyWide()));
+ }
+ }
+ else
+ {
+ if (pUnit->terrainAttackModifier((TerrainTypes)iI) != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_ATTACK", pUnit->terrainAttackModifier((TerrainTypes)iI), GC.getTerrainInfo((TerrainTypes) iI).getTextKeyWide()));
+ }
+
+ if (pUnit->terrainDefenseModifier((TerrainTypes)iI) != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_DEFENSE", pUnit->terrainDefenseModifier((TerrainTypes)iI), GC.getTerrainInfo((TerrainTypes) iI).getTextKeyWide()));
+ }
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumFeatureInfos(); ++iI)
+ {
+ if (pUnit->featureAttackModifier((FeatureTypes)iI) == pUnit->featureDefenseModifier((FeatureTypes)iI))
+ {
+ if (pUnit->featureAttackModifier((FeatureTypes)iI) != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_STRENGTH", pUnit->featureAttackModifier((FeatureTypes)iI), GC.getFeatureInfo((FeatureTypes) iI).getTextKeyWide()));
+ }
+ }
+ else
+ {
+ if (pUnit->featureAttackModifier((FeatureTypes)iI) != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_ATTACK", pUnit->featureAttackModifier((FeatureTypes)iI), GC.getFeatureInfo((FeatureTypes) iI).getTextKeyWide()));
+ }
+
+ if (pUnit->featureDefenseModifier((FeatureTypes)iI) != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_DEFENSE", pUnit->featureDefenseModifier((FeatureTypes)iI), GC.getFeatureInfo((FeatureTypes) iI).getTextKeyWide()));
+ }
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); ++iI)
+ {
+ if (pUnit->getUnitInfo().getUnitClassAttackModifier(iI) == GC.getUnitInfo(pUnit->getUnitType()).getUnitClassDefenseModifier(iI))
+ {
+ if (pUnit->getUnitInfo().getUnitClassAttackModifier(iI) != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_MOD_VS_TYPE", pUnit->getUnitInfo().getUnitClassAttackModifier(iI), GC.getUnitClassInfo((UnitClassTypes)iI).getTextKeyWide()));
+ }
+ }
+ else
+ {
+ if (pUnit->getUnitInfo().getUnitClassAttackModifier(iI) != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_ATTACK_MOD_VS_CLASS", pUnit->getUnitInfo().getUnitClassAttackModifier(iI), GC.getUnitClassInfo((UnitClassTypes)iI).getTextKeyWide()));
+ }
+
+ if (pUnit->getUnitInfo().getUnitClassDefenseModifier(iI) != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_DEFENSE_MOD_VS_CLASS", pUnit->getUnitInfo().getUnitClassDefenseModifier(iI), GC.getUnitClassInfo((UnitClassTypes) iI).getTextKeyWide()));
+ }
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); ++iI)
+ {
+ if (pUnit->unitCombatModifier((UnitCombatTypes)iI) != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_MOD_VS_TYPE", pUnit->unitCombatModifier((UnitCombatTypes)iI), GC.getUnitCombatInfo((UnitCombatTypes) iI).getTextKeyWide()));
+ }
+ }
+
+ for (iI = 0; iI < NUM_DOMAIN_TYPES; ++iI)
+ {
+ if (pUnit->domainModifier((DomainTypes)iI) != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_MOD_VS_TYPE", pUnit->domainModifier((DomainTypes)iI), GC.getDomainInfo((DomainTypes)iI).getTextKeyWide()));
+ }
+ }
+
+ szTempBuffer.clear();
+ bFirst = true;
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); ++iI)
+ {
+ if (pUnit->getUnitInfo().getTargetUnitClass(iI))
+ {
+ if (bFirst)
+ {
+ bFirst = false;
+ }
+ else
+ {
+ szTempBuffer += L", ";
+ }
+
+ szTempBuffer += CvWString::format(L"%s", GC.getUnitClassInfo((UnitClassTypes)iI).getDescription());
+ }
+ }
+
+ if (!bFirst)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_TARGETS_UNIT_FIRST", szTempBuffer.GetCString()));
+ }
+
+ szTempBuffer.clear();
+ bFirst = true;
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); ++iI)
+ {
+ if (pUnit->getUnitInfo().getDefenderUnitClass(iI))
+ {
+ if (bFirst)
+ {
+ bFirst = false;
+ }
+ else
+ {
+ szTempBuffer += L", ";
+ }
+
+ szTempBuffer += CvWString::format(L"%s", GC.getUnitClassInfo((UnitClassTypes)iI).getDescription());
+ }
+ }
+
+ if (!bFirst)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_DEFENDS_UNIT_FIRST", szTempBuffer.GetCString()));
+ }
+
+ szTempBuffer.clear();
+ bFirst = true;
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); ++iI)
+ {
+ if (pUnit->getUnitInfo().getTargetUnitCombat(iI))
+ {
+ if (bFirst)
+ {
+ bFirst = false;
+ }
+ else
+ {
+ szTempBuffer += L", ";
+ }
+
+ szTempBuffer += CvWString::format(L"%s", GC.getUnitCombatInfo((UnitCombatTypes)iI).getDescription());
+ }
+ }
+
+ if (!bFirst)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_TARGETS_UNIT_FIRST", szTempBuffer.GetCString()));
+ }
+
+ szTempBuffer.clear();
+ bFirst = true;
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); ++iI)
+ {
+ if (pUnit->getUnitInfo().getDefenderUnitCombat(iI))
+ {
+ if (bFirst)
+ {
+ bFirst = false;
+ }
+ else
+ {
+ szTempBuffer += L", ";
+ }
+
+ szTempBuffer += CvWString::format(L"%s", GC.getUnitCombatInfo((UnitCombatTypes)iI).getDescription());
+ }
+ }
+
+ if (!bFirst)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_DEFENDS_UNIT_FIRST", szTempBuffer.GetCString()));
+ }
+
+ szTempBuffer.clear();
+ bFirst = true;
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); ++iI)
+ {
+ if (pUnit->getUnitInfo().getFlankingStrikeUnitClass(iI) > 0)
+ {
+ if (bFirst)
+ {
+ bFirst = false;
+ }
+ else
+ {
+ szTempBuffer += L", ";
+ }
+
+ szTempBuffer += CvWString::format(L"%s", GC.getUnitClassInfo((UnitClassTypes)iI).getDescription());
+ }
+ }
+
+ if (!bFirst)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_FLANKING_STRIKES", szTempBuffer.GetCString()));
+ }
+
+ if (pUnit->bombardRate() > 0)
+ {
+ if (bShort)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_BOMBARD_RATE_SHORT", ((pUnit->bombardRate() * 100) / GC.getMAX_CITY_DEFENSE_DAMAGE())));
+ }
+ else
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_BOMBARD_RATE", ((pUnit->bombardRate() * 100) / GC.getMAX_CITY_DEFENSE_DAMAGE())));
+ }
+ }
+
+ if (pUnit->isSpy())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_IS_SPY"));
+ }
+
+ if (pUnit->getUnitInfo().isNoRevealMap())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_VISIBILITY_MOVE_RANGE"));
+ }
+
+ if (!CvWString(pUnit->getUnitInfo().getHelp()).empty())
+ {
+ szString.append(NEWLINE);
+ szString.append(pUnit->getUnitInfo().getHelp());
+ }
+
+ if (bShift && (gDLL->getChtLvl() > 0))
+ {
+ szTempBuffer.Format(L"\nUnitAI Type = %s.", GC.getUnitAIInfo(pUnit->AI_getUnitAIType()).getDescription());
+ szString.append(szTempBuffer);
+ szTempBuffer.Format(L"\nSacrifice Value = %d.", pUnit->AI_sacrificeValue(NULL));
+ szString.append(szTempBuffer);
+ }
+ }
+}
+
+
+void CvGameTextMgr::setPlotListHelp(CvWStringBuffer &szString, CvPlot* pPlot, bool bOneLine, bool bShort)
+{
+ PROFILE_FUNC();
+
+ int numPromotionInfos = GC.getNumPromotionInfos();
+
+ // if cheatmode and ctrl, display grouping info instead
+ if ((gDLL->getChtLvl() > 0) && gDLL->ctrlKey())
+ {
+ if (pPlot->isVisible(GC.getGameINLINE().getActiveTeam(), GC.getGameINLINE().isDebugMode()))
+ {
+ CvWString szTempString;
+
+ CLLNode* pUnitNode = pPlot->headUnitNode();
+ while(pUnitNode != NULL)
+ {
+ CvUnit* pHeadUnit = ::getUnit(pUnitNode->m_data);
+ pUnitNode = pPlot->nextUnitNode(pUnitNode);
+
+ // is this unit the head of a group, not cargo, and visible?
+ if (pHeadUnit && pHeadUnit->isGroupHead() && !pHeadUnit->isCargo() && !pHeadUnit->isInvisible(GC.getGameINLINE().getActiveTeam(), GC.getGameINLINE().isDebugMode()))
+ {
+ // head unit name and unitai
+ szString.append(CvWString::format(SETCOLR L"%s" ENDCOLR, 255,190,0,255, pHeadUnit->getName().GetCString()));
+ szString.append(CvWString::format(L" (%d)", shortenID(pHeadUnit->getID())));
+ getUnitAIString(szTempString, pHeadUnit->AI_getUnitAIType());
+ szString.append(CvWString::format(SETCOLR L" %s " ENDCOLR, GET_PLAYER(pHeadUnit->getOwnerINLINE()).getPlayerTextColorR(), GET_PLAYER(pHeadUnit->getOwnerINLINE()).getPlayerTextColorG(), GET_PLAYER(pHeadUnit->getOwnerINLINE()).getPlayerTextColorB(), GET_PLAYER(pHeadUnit->getOwnerINLINE()).getPlayerTextColorA(), szTempString.GetCString()));
+
+ // promotion icons
+ for (int iPromotionIndex = 0; iPromotionIndex < numPromotionInfos; iPromotionIndex++)
+ {
+ PromotionTypes ePromotion = (PromotionTypes)iPromotionIndex;
+ if (pHeadUnit->isHasPromotion(ePromotion))
+ {
+ szString.append(CvWString::format(L"
", GC.getPromotionInfo(ePromotion).getButton()));
+ }
+ }
+
+ // group
+ CvSelectionGroup* pHeadGroup = pHeadUnit->getGroup();
+ FAssertMsg(pHeadGroup != NULL, "unit has NULL group");
+ if (pHeadGroup->getNumUnits() > 1)
+ {
+ szString.append(CvWString::format(L"\nGroup:%d [%d units]", shortenID(pHeadGroup->getID()), pHeadGroup->getNumUnits()));
+
+ // get average damage
+ int iAverageDamage = 0;
+ CLLNode* pUnitNode = pHeadGroup->headUnitNode();
+ while (pUnitNode != NULL)
+ {
+ CvUnit* pLoopUnit = ::getUnit(pUnitNode->m_data);
+ pUnitNode = pHeadGroup->nextUnitNode(pUnitNode);
+
+ iAverageDamage += (pLoopUnit->getDamage() * pLoopUnit->maxHitPoints()) / 100;
+ }
+ iAverageDamage /= pHeadGroup->getNumUnits();
+ if (iAverageDamage > 0)
+ {
+ szString.append(CvWString::format(L" %d%%", 100 - iAverageDamage));
+ }
+ }
+
+ // mission ai
+ MissionAITypes eMissionAI = pHeadGroup->AI_getMissionAIType();
+ if (eMissionAI != NO_MISSIONAI)
+ {
+ getMissionAIString(szTempString, eMissionAI);
+ szString.append(CvWString::format(SETCOLR L"\n%s" ENDCOLR, TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), szTempString.GetCString()));
+ }
+
+ // mission
+ MissionTypes eMissionType = (MissionTypes) pHeadGroup->getMissionType(0);
+ if (eMissionType != NO_MISSION)
+ {
+ getMissionTypeString(szTempString, eMissionType);
+ szString.append(CvWString::format(SETCOLR L"\n%s" ENDCOLR, TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), szTempString.GetCString()));
+ }
+
+ // mission unit
+ CvUnit* pMissionUnit = pHeadGroup->AI_getMissionAIUnit();
+ if (pMissionUnit != NULL && (eMissionAI != NO_MISSIONAI || eMissionType != NO_MISSION))
+ {
+ // mission unit
+ szString.append(L"\n to ");
+ szString.append(CvWString::format(SETCOLR L"%s" ENDCOLR, GET_PLAYER(pMissionUnit->getOwnerINLINE()).getPlayerTextColorR(), GET_PLAYER(pMissionUnit->getOwnerINLINE()).getPlayerTextColorG(), GET_PLAYER(pMissionUnit->getOwnerINLINE()).getPlayerTextColorB(), GET_PLAYER(pMissionUnit->getOwnerINLINE()).getPlayerTextColorA(), pMissionUnit->getName().GetCString()));
+ szString.append(CvWString::format(L"(%d) G:%d", shortenID(pMissionUnit->getID()), shortenID(pMissionUnit->getGroupID())));
+ getUnitAIString(szTempString, pMissionUnit->AI_getUnitAIType());
+ szString.append(CvWString::format(SETCOLR L" %s" ENDCOLR, GET_PLAYER(pMissionUnit->getOwnerINLINE()).getPlayerTextColorR(), GET_PLAYER(pMissionUnit->getOwnerINLINE()).getPlayerTextColorG(), GET_PLAYER(pMissionUnit->getOwnerINLINE()).getPlayerTextColorB(), GET_PLAYER(pMissionUnit->getOwnerINLINE()).getPlayerTextColorA(), szTempString.GetCString()));
+ }
+
+ // mission plot
+ if (eMissionAI != NO_MISSIONAI || eMissionType != NO_MISSION)
+ {
+ // first try the plot from the missionAI
+ CvPlot* pMissionPlot = pHeadGroup->AI_getMissionAIPlot();
+
+ // if MissionAI does not have a plot, get one from the mission itself
+ if (pMissionPlot == NULL && eMissionType != NO_MISSION)
+ {
+ switch (eMissionType)
+ {
+ case MISSION_MOVE_TO:
+ case MISSION_ROUTE_TO:
+ pMissionPlot = GC.getMapINLINE().plotINLINE(pHeadGroup->getMissionData1(0), pHeadGroup->getMissionData2(0));
+ break;
+
+ case MISSION_MOVE_TO_UNIT:
+ if (pMissionUnit != NULL)
+ {
+ pMissionPlot = pMissionUnit->plot();
+ }
+ break;
+ }
+ }
+
+ if (pMissionPlot != NULL)
+ {
+ szString.append(CvWString::format(L"\n [%d,%d]", pMissionPlot->getX_INLINE(), pMissionPlot->getY_INLINE()));
+
+ CvCity* pCity = pMissionPlot->getWorkingCity();
+ if (pCity != NULL)
+ {
+ szString.append(L" (");
+
+ if (!pMissionPlot->isCity())
+ {
+ DirectionTypes eDirection = estimateDirection(dxWrap(pMissionPlot->getX_INLINE() - pCity->plot()->getX_INLINE()), dyWrap(pMissionPlot->getY_INLINE() - pCity->plot()->getY_INLINE()));
+
+ getDirectionTypeString(szTempString, eDirection);
+ szString.append(CvWString::format(L"%s of ", szTempString.GetCString()));
+ }
+
+ szString.append(CvWString::format(SETCOLR L"%s" ENDCOLR L")", GET_PLAYER(pCity->getOwnerINLINE()).getPlayerTextColorR(), GET_PLAYER(pCity->getOwnerINLINE()).getPlayerTextColorG(), GET_PLAYER(pCity->getOwnerINLINE()).getPlayerTextColorB(), GET_PLAYER(pCity->getOwnerINLINE()).getPlayerTextColorA(), pCity->getName().GetCString()));
+ }
+ else
+ {
+ if (pMissionPlot != pPlot)
+ {
+ DirectionTypes eDirection = estimateDirection(dxWrap(pMissionPlot->getX_INLINE() - pPlot->getX_INLINE()), dyWrap(pMissionPlot->getY_INLINE() - pPlot->getY_INLINE()));
+
+ getDirectionTypeString(szTempString, eDirection);
+ szString.append(CvWString::format(L" (%s)", szTempString.GetCString()));
+ }
+
+ PlayerTypes eMissionPlotOwner = pMissionPlot->getOwnerINLINE();
+ if (eMissionPlotOwner != NO_PLAYER)
+ {
+ szString.append(CvWString::format(L", " SETCOLR L"%s" ENDCOLR, GET_PLAYER(eMissionPlotOwner).getPlayerTextColorR(), GET_PLAYER(eMissionPlotOwner).getPlayerTextColorG(), GET_PLAYER(eMissionPlotOwner).getPlayerTextColorB(), GET_PLAYER(eMissionPlotOwner).getPlayerTextColorA(), GET_PLAYER(eMissionPlotOwner).getName()));
+ }
+ }
+ }
+ }
+
+ // display cargo for head unit
+ std::vector aCargoUnits;
+ pHeadUnit->getCargoUnits(aCargoUnits);
+ for (uint i = 0; i < aCargoUnits.size(); ++i)
+ {
+ CvUnit* pCargoUnit = aCargoUnits[i];
+ if (!pCargoUnit->isInvisible(GC.getGameINLINE().getActiveTeam(), GC.getGameINLINE().isDebugMode()))
+ {
+ // name and unitai
+ szString.append(CvWString::format(SETCOLR L"\n %s" ENDCOLR, TEXT_COLOR("COLOR_ALT_HIGHLIGHT_TEXT"), pCargoUnit->getName().GetCString()));
+ szString.append(CvWString::format(L"(%d)", shortenID(pCargoUnit->getID())));
+ getUnitAIString(szTempString, pCargoUnit->AI_getUnitAIType());
+ szString.append(CvWString::format(SETCOLR L" %s " ENDCOLR, GET_PLAYER(pCargoUnit->getOwnerINLINE()).getPlayerTextColorR(), GET_PLAYER(pCargoUnit->getOwnerINLINE()).getPlayerTextColorG(), GET_PLAYER(pCargoUnit->getOwnerINLINE()).getPlayerTextColorB(), GET_PLAYER(pCargoUnit->getOwnerINLINE()).getPlayerTextColorA(), szTempString.GetCString()));
+
+ // promotion icons
+ for (int iPromotionIndex = 0; iPromotionIndex < numPromotionInfos; iPromotionIndex++)
+ {
+ PromotionTypes ePromotion = (PromotionTypes)iPromotionIndex;
+ if (pCargoUnit->isHasPromotion(ePromotion))
+ {
+ szString.append(CvWString::format(L"
", GC.getPromotionInfo(ePromotion).getButton()));
+ }
+ }
+ }
+ }
+
+ // display grouped units
+ CLLNode* pUnitNode3 = pPlot->headUnitNode();
+ while(pUnitNode3 != NULL)
+ {
+ CvUnit* pUnit = ::getUnit(pUnitNode3->m_data);
+ pUnitNode3 = pPlot->nextUnitNode(pUnitNode3);
+
+ // is this unit not head, in head's group and visible?
+ if (pUnit && (pUnit != pHeadUnit) && (pUnit->getGroupID() == pHeadUnit->getGroupID()) && !pUnit->isInvisible(GC.getGameINLINE().getActiveTeam(), GC.getGameINLINE().isDebugMode()))
+ {
+ FAssertMsg(!pUnit->isCargo(), "unit is cargo but head unit is not cargo");
+ // name and unitai
+ szString.append(CvWString::format(SETCOLR L"\n-%s" ENDCOLR, TEXT_COLOR("COLOR_UNIT_TEXT"), pUnit->getName().GetCString()));
+ szString.append(CvWString::format(L" (%d)", shortenID(pUnit->getID())));
+ getUnitAIString(szTempString, pUnit->AI_getUnitAIType());
+ szString.append(CvWString::format(SETCOLR L" %s " ENDCOLR, GET_PLAYER(pUnit->getOwnerINLINE()).getPlayerTextColorR(), GET_PLAYER(pUnit->getOwnerINLINE()).getPlayerTextColorG(), GET_PLAYER(pUnit->getOwnerINLINE()).getPlayerTextColorB(), GET_PLAYER(pUnit->getOwnerINLINE()).getPlayerTextColorA(), szTempString.GetCString()));
+
+ // promotion icons
+ for (int iPromotionIndex = 0; iPromotionIndex < numPromotionInfos; iPromotionIndex++)
+ {
+ PromotionTypes ePromotion = (PromotionTypes)iPromotionIndex;
+ if (pUnit->isHasPromotion(ePromotion))
+ {
+ szString.append(CvWString::format(L"
", GC.getPromotionInfo(ePromotion).getButton()));
+ }
+ }
+
+ // display cargo for loop unit
+ std::vector aLoopCargoUnits;
+ pUnit->getCargoUnits(aLoopCargoUnits);
+ for (uint i = 0; i < aLoopCargoUnits.size(); ++i)
+ {
+ CvUnit* pCargoUnit = aLoopCargoUnits[i];
+ if (!pCargoUnit->isInvisible(GC.getGameINLINE().getActiveTeam(), GC.getGameINLINE().isDebugMode()))
+ {
+ // name and unitai
+ szString.append(CvWString::format(SETCOLR L"\n %s" ENDCOLR, TEXT_COLOR("COLOR_ALT_HIGHLIGHT_TEXT"), pCargoUnit->getName().GetCString()));
+ szString.append(CvWString::format(L"(%d)", shortenID(pCargoUnit->getID())));
+ getUnitAIString(szTempString, pCargoUnit->AI_getUnitAIType());
+ szString.append(CvWString::format(SETCOLR L" %s " ENDCOLR, GET_PLAYER(pCargoUnit->getOwnerINLINE()).getPlayerTextColorR(), GET_PLAYER(pCargoUnit->getOwnerINLINE()).getPlayerTextColorG(), GET_PLAYER(pCargoUnit->getOwnerINLINE()).getPlayerTextColorB(), GET_PLAYER(pCargoUnit->getOwnerINLINE()).getPlayerTextColorA(), szTempString.GetCString()));
+
+ // promotion icons
+ for (int iPromotionIndex = 0; iPromotionIndex < numPromotionInfos; iPromotionIndex++)
+ {
+ PromotionTypes ePromotion = (PromotionTypes)iPromotionIndex;
+ if (pCargoUnit->isHasPromotion(ePromotion))
+ {
+ szString.append(CvWString::format(L"
", GC.getPromotionInfo(ePromotion).getButton()));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // double space non-empty groups
+ if (pHeadGroup->getNumUnits() > 1 || pHeadUnit->hasCargo())
+ {
+ szString.append(NEWLINE);
+ }
+
+ szString.append(NEWLINE);
+ }
+ }
+ }
+
+ return;
+ }
+
+
+ CvUnit* pLoopUnit;
+ static const uint iMaxNumUnits = 15;
+ static std::vector apUnits;
+ static std::vector aiUnitNumbers;
+ static std::vector aiUnitStrength;
+ static std::vector aiUnitMaxStrength;
+ static std::vector plotUnits;
+
+ GC.getGameINLINE().getPlotUnits(pPlot, plotUnits);
+
+ int iNumVisibleUnits = 0;
+ if (pPlot->isVisible(GC.getGameINLINE().getActiveTeam(), GC.getGameINLINE().isDebugMode()))
+ {
+ CLLNode* pUnitNode5 = pPlot->headUnitNode();
+ while(pUnitNode5 != NULL)
+ {
+ CvUnit* pUnit = ::getUnit(pUnitNode5->m_data);
+ pUnitNode5 = pPlot->nextUnitNode(pUnitNode5);
+
+ if (pUnit && !pUnit->isInvisible(GC.getGameINLINE().getActiveTeam(), GC.getGameINLINE().isDebugMode()))
+ {
+ ++iNumVisibleUnits;
+ }
+ }
+ }
+
+ apUnits.erase(apUnits.begin(), apUnits.end());
+
+ if (iNumVisibleUnits > iMaxNumUnits)
+ {
+ aiUnitNumbers.erase(aiUnitNumbers.begin(), aiUnitNumbers.end());
+ aiUnitStrength.erase(aiUnitStrength.begin(), aiUnitStrength.end());
+ aiUnitMaxStrength.erase(aiUnitMaxStrength.begin(), aiUnitMaxStrength.end());
+
+ if (m_apbPromotion.size() == 0)
+ {
+ for (int iI = 0; iI < (GC.getNumUnitInfos() * MAX_PLAYERS); ++iI)
+ {
+ m_apbPromotion.push_back(new int[numPromotionInfos]);
+ }
+ }
+
+ for (int iI = 0; iI < (GC.getNumUnitInfos() * MAX_PLAYERS); ++iI)
+ {
+ aiUnitNumbers.push_back(0);
+ aiUnitStrength.push_back(0);
+ aiUnitMaxStrength.push_back(0);
+ for (int iJ = 0; iJ < numPromotionInfos; iJ++)
+ {
+ m_apbPromotion[iI][iJ] = 0;
+ }
+ }
+ }
+
+ int iCount = 0;
+ for (int iI = iMaxNumUnits; iI < iNumVisibleUnits && iI < (int) plotUnits.size(); ++iI)
+ {
+ pLoopUnit = plotUnits[iI];
+
+ if (pLoopUnit != NULL && pLoopUnit != pPlot->getCenterUnit())
+ {
+ apUnits.push_back(pLoopUnit);
+
+ if (iNumVisibleUnits > iMaxNumUnits)
+ {
+ int iIndex = pLoopUnit->getUnitType() * MAX_PLAYERS + pLoopUnit->getOwner();
+ if (aiUnitNumbers[iIndex] == 0)
+ {
+ ++iCount;
+ }
+ ++aiUnitNumbers[iIndex];
+
+ int iBase = (DOMAIN_AIR == pLoopUnit->getDomainType() ? pLoopUnit->airBaseCombatStr() : pLoopUnit->baseCombatStr());
+ if (iBase > 0 && pLoopUnit->maxHitPoints() > 0)
+ {
+ aiUnitMaxStrength[iIndex] += 100 * iBase;
+ aiUnitStrength[iIndex] += (100 * iBase * pLoopUnit->currHitPoints()) / pLoopUnit->maxHitPoints();
+ }
+
+ for (int iJ = 0; iJ < numPromotionInfos; iJ++)
+ {
+ if (pLoopUnit->isHasPromotion((PromotionTypes)iJ))
+ {
+ ++m_apbPromotion[iIndex][iJ];
+ }
+ }
+ }
+ }
+ }
+
+
+ if (iNumVisibleUnits > 0)
+ {
+ if (pPlot->getCenterUnit())
+ {
+ setUnitHelp(szString, pPlot->getCenterUnit(), iNumVisibleUnits > iMaxNumUnits, true);
+ }
+
+ uint iNumShown = std::min(iMaxNumUnits, iNumVisibleUnits);
+ for (uint iI = 0; iI < iNumShown && iI < (int) plotUnits.size(); ++iI)
+ {
+ CvUnit* pLoopUnit = plotUnits[iI];
+ if (pLoopUnit != pPlot->getCenterUnit())
+ {
+ szString.append(NEWLINE);
+ setUnitHelp(szString, pLoopUnit, true, true);
+ }
+ }
+
+ bool bFirst = true;
+ if (iNumVisibleUnits > iMaxNumUnits)
+ {
+ for (int iI = 0; iI < GC.getNumUnitInfos(); ++iI)
+ {
+ for (int iJ = 0; iJ < MAX_PLAYERS; iJ++)
+ {
+ int iIndex = iI * MAX_PLAYERS + iJ;
+
+ if (aiUnitNumbers[iIndex] > 0)
+ {
+ if (iCount < 5 || bFirst)
+ {
+ szString.append(NEWLINE);
+ bFirst = false;
+ }
+ else
+ {
+ szString.append(L", ");
+ }
+ szString.append(CvWString::format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR("COLOR_UNIT_TEXT"), GC.getUnitInfo((UnitTypes)iI).getDescription()));
+
+ szString.append(CvWString::format(L" (%d)", aiUnitNumbers[iIndex]));
+
+ if (aiUnitMaxStrength[iIndex] > 0)
+ {
+ int iBase = (aiUnitMaxStrength[iIndex] / aiUnitNumbers[iIndex]) / 100;
+ int iCurrent = (aiUnitStrength[iIndex] / aiUnitNumbers[iIndex]) / 100;
+ int iCurrent100 = (aiUnitStrength[iIndex] / aiUnitNumbers[iIndex]) % 100;
+ if (0 == iCurrent100)
+ {
+ if (iBase == iCurrent)
+ {
+ szString.append(CvWString::format(L" %d", iBase));
+ }
+ else
+ {
+ szString.append(CvWString::format(L" %d/%d", iCurrent, iBase));
+ }
+ }
+ else
+ {
+ szString.append(CvWString::format(L" %d.%02d/%d", iCurrent, iCurrent100, iBase));
+ }
+ szString.append(CvWString::format(L"%c", gDLL->getSymbolID(STRENGTH_CHAR)));
+ }
+
+
+ for (int iK = 0; iK < numPromotionInfos; iK++)
+ {
+ if (m_apbPromotion[iIndex][iK] > 0)
+ {
+ szString.append(CvWString::format(L"%d
", m_apbPromotion[iIndex][iK], GC.getPromotionInfo((PromotionTypes)iK).getButton()));
+ }
+ }
+
+ if (iJ != GC.getGameINLINE().getActivePlayer() && !GC.getUnitInfo((UnitTypes)iI).isAnimal() && !GC.getUnitInfo((UnitTypes)iI).isHiddenNationality())
+ {
+ szString.append(L", ");
+ szString.append(CvWString::format(SETCOLR L"%s" ENDCOLR, GET_PLAYER((PlayerTypes)iJ).getPlayerTextColorR(), GET_PLAYER((PlayerTypes)iJ).getPlayerTextColorG(), GET_PLAYER((PlayerTypes)iJ).getPlayerTextColorB(), GET_PLAYER((PlayerTypes)iJ).getPlayerTextColorA(), GET_PLAYER((PlayerTypes)iJ).getName()));
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+// Returns true if help was given...
+bool CvGameTextMgr::setCombatPlotHelp(CvWStringBuffer &szString, CvPlot* pPlot)
+{
+ PROFILE_FUNC();
+
+ CvUnit* pAttacker;
+ CvUnit* pDefender;
+ CvWString szTempBuffer;
+ CvWString szOffenseOdds;
+ CvWString szDefenseOdds;
+ bool bValid;
+ int iModifier;
+
+ if (gDLL->getInterfaceIFace()->getLengthSelectionList() == 0)
+ {
+ return false;
+ }
+
+ bValid = false;
+
+ switch (gDLL->getInterfaceIFace()->getSelectionList()->getDomainType())
+ {
+ case DOMAIN_SEA:
+ bValid = pPlot->isWater();
+ break;
+
+ case DOMAIN_AIR:
+ bValid = true;
+ break;
+
+ case DOMAIN_LAND:
+ bValid = !(pPlot->isWater());
+ break;
+
+ case DOMAIN_IMMOBILE:
+ break;
+
+ default:
+ FAssert(false);
+ break;
+ }
+
+ if (!bValid)
+ {
+ return false;
+ }
+
+ int iOdds;
+ pAttacker = gDLL->getInterfaceIFace()->getSelectionList()->AI_getBestGroupAttacker(pPlot, false, iOdds);
+
+ if (pAttacker == NULL)
+ {
+ pAttacker = gDLL->getInterfaceIFace()->getSelectionList()->AI_getBestGroupAttacker(pPlot, false, iOdds, true);
+ }
+
+ if (pAttacker != NULL)
+ {
+ pDefender = pPlot->getBestDefender(NO_PLAYER, pAttacker->getOwnerINLINE(), pAttacker, false, NO_TEAM == pAttacker->getDeclareWarMove(pPlot));
+
+ if (pDefender != NULL && pDefender != pAttacker && pDefender->canDefend(pPlot) && pAttacker->canAttack(*pDefender))
+ {
+ if (pAttacker->getDomainType() != DOMAIN_AIR)
+ {
+ int iCombatOdds = getCombatOdds(pAttacker, pDefender);
+
+ if (pAttacker->combatLimit() >= GC.getMAX_HIT_POINTS())
+ {
+ if (iCombatOdds > 999)
+ {
+ szTempBuffer = L"> 99.9";
+ }
+ else if (iCombatOdds < 1)
+ {
+ szTempBuffer = L"< 0.1";
+ }
+ else
+ {
+ szTempBuffer.Format(L"%.1f", ((float)iCombatOdds) / 10.0f);
+ }
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_ODDS", szTempBuffer.GetCString()));
+ }
+
+
+ int iWithdrawal = 0;
+
+ if (pAttacker->combatLimit() < GC.getMAX_HIT_POINTS())
+ {
+ iWithdrawal += 100 * iCombatOdds;
+ }
+
+ iWithdrawal += std::min(100, pAttacker->withdrawalProbability()) * (1000 - iCombatOdds);
+
+ if (iWithdrawal > 0 || pAttacker->combatLimit() < GC.getMAX_HIT_POINTS())
+ {
+ if (iWithdrawal > 99900)
+ {
+ szTempBuffer = L"> 99.9";
+ }
+ else if (iWithdrawal < 100)
+ {
+ szTempBuffer = L"< 0.1";
+ }
+ else
+ {
+ szTempBuffer.Format(L"%.1f", iWithdrawal / 1000.0f);
+ }
+
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_ODDS_RETREAT", szTempBuffer.GetCString()));
+ }
+
+ //szTempBuffer.Format(L"AI odds: %d%%", iOdds);
+ //szString += NEWLINE + szTempBuffer;
+ }
+
+ szOffenseOdds.Format(L"%.2f", ((pAttacker->getDomainType() == DOMAIN_AIR) ? pAttacker->airCurrCombatStrFloat(pDefender) : pAttacker->currCombatStrFloat(NULL, NULL)));
+ szDefenseOdds.Format(L"%.2f", pDefender->currCombatStrFloat(pPlot, pAttacker));
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_ODDS_VS", szOffenseOdds.GetCString(), szDefenseOdds.GetCString()));
+
+ szString.append(L' ');//XXX
+
+ szString.append(gDLL->getText("TXT_KEY_COLOR_POSITIVE"));
+
+ szString.append(L' ');//XXX
+
+ iModifier = pAttacker->getExtraCombatPercent();
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_EXTRA_STRENGTH", iModifier));
+ }
+
+ iModifier = pAttacker->unitClassAttackModifier(pDefender->getUnitClassType());
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_MOD_VS_TYPE", iModifier, GC.getUnitClassInfo(pDefender->getUnitClassType()).getTextKeyWide()));
+ }
+
+ if (pDefender->getUnitCombatType() != NO_UNITCOMBAT)
+ {
+ iModifier = pAttacker->unitCombatModifier(pDefender->getUnitCombatType());
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_MOD_VS_TYPE", iModifier, GC.getUnitCombatInfo(pDefender->getUnitCombatType()).getTextKeyWide()));
+ }
+ }
+
+ iModifier = pAttacker->domainModifier(pDefender->getDomainType());
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_MOD_VS_TYPE", iModifier, GC.getDomainInfo(pDefender->getDomainType()).getTextKeyWide()));
+ }
+
+ if (pPlot->isCity(true, pDefender->getTeam()))
+ {
+ iModifier = pAttacker->cityAttackModifier();
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_CITY_MOD", iModifier));
+ }
+ }
+
+ if (pPlot->isHills())
+ {
+ iModifier = pAttacker->hillsAttackModifier();
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_HILLS_MOD", iModifier));
+ }
+ }
+
+ if (pPlot->getFeatureType() != NO_FEATURE)
+ {
+ iModifier = pAttacker->featureAttackModifier(pPlot->getFeatureType());
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_UNIT_MOD", iModifier, GC.getFeatureInfo(pPlot->getFeatureType()).getTextKeyWide()));
+ }
+ }
+ else
+ {
+ iModifier = pAttacker->terrainAttackModifier(pPlot->getTerrainType());
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_UNIT_MOD", iModifier, GC.getTerrainInfo(pPlot->getTerrainType()).getTextKeyWide()));
+ }
+ }
+
+ iModifier = pAttacker->getKamikazePercent();
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_KAMIKAZE_MOD", iModifier));
+ }
+
+ if (pDefender->isAnimal())
+ {
+ iModifier = -GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAnimalCombatModifier();
+
+ iModifier += pAttacker->getUnitInfo().getAnimalCombatModifier();
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_ANIMAL_COMBAT_MOD", iModifier));
+ }
+ }
+
+ if (pDefender->isBarbarian())
+ {
+ iModifier = -GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getBarbarianCombatModifier();
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_BARBARIAN_COMBAT_MOD", iModifier));
+ }
+ }
+
+ if (!(pDefender->immuneToFirstStrikes()))
+ {
+ if (pAttacker->maxFirstStrikes() > 0)
+ {
+ if (pAttacker->firstStrikes() == pAttacker->maxFirstStrikes())
+ {
+ if (pAttacker->firstStrikes() == 1)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_ONE_FIRST_STRIKE"));
+ }
+ else
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_NUM_FIRST_STRIKES", pAttacker->firstStrikes()));
+ }
+ }
+ else
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_FIRST_STRIKE_CHANCES", pAttacker->firstStrikes(), pAttacker->maxFirstStrikes()));
+ }
+ }
+ }
+
+ if (pAttacker->isHurt())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_HP", pAttacker->currHitPoints(), pAttacker->maxHitPoints()));
+ }
+
+ szString.append(gDLL->getText("TXT_KEY_COLOR_REVERT"));
+
+ szString.append(L' ');//XXX
+
+ szString.append(gDLL->getText("TXT_KEY_COLOR_NEGATIVE"));
+
+ szString.append(L' ');//XXX
+
+ if (!(pAttacker->isRiver()))
+ {
+ if (pAttacker->plot()->isRiverCrossing(directionXY(pAttacker->plot(), pPlot)))
+ {
+ iModifier = GC.getRIVER_ATTACK_MODIFIER();
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_RIVER_MOD", -(iModifier)));
+ }
+ }
+ }
+
+ if (!(pAttacker->isAmphib()))
+ {
+ if (!(pPlot->isWater()) && pAttacker->plot()->isWater())
+ {
+ iModifier = GC.getAMPHIB_ATTACK_MODIFIER();
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_AMPHIB_MOD", -(iModifier)));
+ }
+ }
+ }
+
+ iModifier = pDefender->getExtraCombatPercent();
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_EXTRA_STRENGTH", iModifier));
+ }
+
+ iModifier = pDefender->unitClassDefenseModifier(pAttacker->getUnitClassType());
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_MOD_VS_TYPE", iModifier, GC.getUnitClassInfo(pAttacker->getUnitClassType()).getTextKeyWide()));
+ }
+
+ if (pAttacker->getUnitCombatType() != NO_UNITCOMBAT)
+ {
+ iModifier = pDefender->unitCombatModifier(pAttacker->getUnitCombatType());
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_MOD_VS_TYPE", iModifier, GC.getUnitCombatInfo(pAttacker->getUnitCombatType()).getTextKeyWide()));
+ }
+ }
+
+ iModifier = pDefender->domainModifier(pAttacker->getDomainType());
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_MOD_VS_TYPE", iModifier, GC.getDomainInfo(pAttacker->getDomainType()).getTextKeyWide()));
+ }
+
+ if (!(pDefender->noDefensiveBonus()))
+ {
+ iModifier = pPlot->defenseModifier(pDefender->getTeam(), (pAttacker != NULL) ? pAttacker->ignoreBuildingDefense() : true);
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_TILE_MOD", iModifier));
+ }
+ }
+
+ iModifier = pDefender->fortifyModifier();
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_FORTIFY_MOD", iModifier));
+ }
+
+ if (pPlot->isCity(true, pDefender->getTeam()))
+ {
+ iModifier = pDefender->cityDefenseModifier();
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_CITY_MOD", iModifier));
+ }
+ }
+
+ if (pPlot->isHills())
+ {
+ iModifier = pDefender->hillsDefenseModifier();
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_HILLS_MOD", iModifier));
+ }
+ }
+
+ if (pPlot->getFeatureType() != NO_FEATURE)
+ {
+ iModifier = pDefender->featureDefenseModifier(pPlot->getFeatureType());
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_UNIT_MOD", iModifier, GC.getFeatureInfo(pPlot->getFeatureType()).getTextKeyWide()));
+ }
+ }
+ else
+ {
+ iModifier = pDefender->terrainDefenseModifier(pPlot->getTerrainType());
+
+ if (iModifier != 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_UNIT_MOD", iModifier, GC.getTerrainInfo(pPlot->getTerrainType()).getTextKeyWide()));
+ }
+ }
+
+ if (!(pAttacker->immuneToFirstStrikes()))
+ {
+ if (pDefender->maxFirstStrikes() > 0)
+ {
+ if (pDefender->firstStrikes() == pDefender->maxFirstStrikes())
+ {
+ if (pDefender->firstStrikes() == 1)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_ONE_FIRST_STRIKE"));
+ }
+ else
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_NUM_FIRST_STRIKES", pDefender->firstStrikes()));
+ }
+ }
+ else
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_UNIT_FIRST_STRIKE_CHANCES", pDefender->firstStrikes(), pDefender->maxFirstStrikes()));
+ }
+ }
+ }
+
+ if (pDefender->isHurt())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_COMBAT_PLOT_HP", pDefender->currHitPoints(), pDefender->maxHitPoints()));
+ }
+
+ if ((gDLL->getChtLvl() > 0))
+ {
+ szTempBuffer.Format(L"\nStack Compare Value = %d",
+ gDLL->getInterfaceIFace()->getSelectionList()->AI_compareStacks(pPlot, false));
+ szString.append(szTempBuffer);
+
+ int iOurStrengthDefense = GET_PLAYER(GC.getGameINLINE().getActivePlayer()).AI_getOurPlotStrength(pPlot, 1, true, false);
+ int iOurStrengthOffense = GET_PLAYER(GC.getGameINLINE().getActivePlayer()).AI_getOurPlotStrength(pPlot, 1, false, false);
+ szTempBuffer.Format(L"\nPlot Strength(Ours)= d%d, o%d", iOurStrengthDefense, iOurStrengthOffense);
+ szString.append(szTempBuffer);
+ int iEnemyStrengthDefense = GET_PLAYER(GC.getGameINLINE().getActivePlayer()).AI_getEnemyPlotStrength(pPlot, 1, true, false);
+ int iEnemyStrengthOffense = GET_PLAYER(GC.getGameINLINE().getActivePlayer()).AI_getEnemyPlotStrength(pPlot, 1, false, false);
+ szTempBuffer.Format(L"\nPlot Strength(Enemy)= d%d, o%d", iEnemyStrengthDefense, iEnemyStrengthOffense);
+ szString.append(szTempBuffer);
+ }
+
+ szString.append(gDLL->getText("TXT_KEY_COLOR_REVERT"));
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// DO NOT REMOVE - needed for font testing - Moose
+void createTestFontString(CvWStringBuffer& szString)
+{
+ int iI;
+ szString.assign(L"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[×]^_`abcdefghijklmnopqrstuvwxyz\n");
+ //szString.append(L"{}~\\ßÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¿¡«»°ŠŒŽšœž™©®€£¢”‘“…’");
+ for (iI=0;iIgetSymbolID(iI)));
+}
+
+void CvGameTextMgr::setPlotHelp(CvWStringBuffer& szString, CvPlot* pPlot)
+{
+ PROFILE_FUNC();
+
+ int iI;
+
+ CvWString szTempBuffer;
+ ImprovementTypes eImprovement;
+ PlayerTypes eRevealOwner;
+ BonusTypes eBonus;
+ bool bShift;
+ bool bAlt;
+ bool bCtrl;
+ bool bFound;
+ int iDefenseModifier;
+ int iYield;
+ int iTurns;
+
+ bShift = gDLL->shiftKey();
+ bAlt = gDLL->altKey();
+ bCtrl = gDLL->ctrlKey();
+
+ if (bCtrl && (gDLL->getChtLvl() > 0))
+ {
+ if (bShift && pPlot->headUnitNode() != NULL)
+ {
+ return;
+ }
+
+ if (pPlot->getOwnerINLINE() != NO_PLAYER)
+ {
+ int iPlotDanger = GET_PLAYER(pPlot->getOwnerINLINE()).AI_getPlotDanger(pPlot, 2);
+ if (iPlotDanger > 0)
+ {
+ szString.append(CvWString::format(L"\nPlot Danger = %d", iPlotDanger));
+ }
+ }
+
+ CvCity* pPlotCity = pPlot->getPlotCity();
+ if (pPlotCity != NULL)
+ {
+ PlayerTypes ePlayer = pPlot->getOwnerINLINE();
+ CvPlayerAI& kPlayer = GET_PLAYER(ePlayer);
+
+ int iCityDefenders = pPlot->plotCount(PUF_canDefendGroupHead, -1, -1, ePlayer, NO_TEAM, PUF_isCityAIType);
+ int iAttackGroups = pPlot->plotCount(PUF_isUnitAIType, UNITAI_ATTACK, -1, ePlayer);
+ szString.append(CvWString::format(L"\nDefenders [D+A]/N ([%d + %d] / %d)", iCityDefenders, iAttackGroups, pPlotCity->AI_neededDefenders()));
+
+ szString.append(CvWString::format(L"\nFloating Defenders H/N (%d / %d)", kPlayer.AI_getTotalFloatingDefenders(pPlotCity->area()), kPlayer.AI_getTotalFloatingDefendersNeeded(pPlotCity->area())));
+ szString.append(CvWString::format(L"\nAir Defenders H/N (%d / %d)", pPlotCity->plot()->plotCount(PUF_canAirDefend, -1, -1, pPlotCity->getOwnerINLINE(), NO_TEAM, PUF_isDomainType, DOMAIN_AIR), pPlotCity->AI_neededAirDefenders()));
+// int iHostileUnits = kPlayer.AI_countNumAreaHostileUnits(pPlotCity->area());
+// if (iHostileUnits > 0)
+// {
+// szString+=CvWString::format(L"\nHostiles = %d", iHostileUnits);
+// }
+
+ szString.append(CvWString::format(L"\nThreat C/P (%d / %d)", pPlotCity->AI_cityThreat(), kPlayer.AI_getTotalAreaCityThreat(pPlotCity->area())));
+
+ bool bFirst = true;
+ for (int iI = 0; iI < MAX_PLAYERS; ++iI)
+ {
+ PlayerTypes eLoopPlayer = (PlayerTypes) iI;
+ CvPlayerAI& kLoopPlayer = GET_PLAYER(eLoopPlayer);
+ if ((eLoopPlayer != ePlayer) && kLoopPlayer.isAlive())
+ {
+ int iCloseness = pPlotCity->AI_playerCloseness(eLoopPlayer, 7);
+ if (iCloseness != 0)
+ {
+ if (bFirst)
+ {
+ bFirst = false;
+
+ szString.append(CvWString::format(L"\n\nCloseness:"));
+ }
+
+ szString.append(CvWString::format(L"\n%s(7) : %d", kLoopPlayer.getName(), iCloseness));
+ szString.append(CvWString::format(L" (%d, ", kPlayer.AI_playerCloseness(eLoopPlayer, 7)));
+ if (kPlayer.getTeam() != kLoopPlayer.getTeam())
+ {
+ szString.append(CvWString::format(L"%d)", GET_TEAM(kPlayer.getTeam()).AI_teamCloseness(kLoopPlayer.getTeam(), 7)));
+ }
+ else
+ {
+ szString.append(CvWString::format(L"-)"));
+ }
+ }
+ }
+ }
+
+ int iWorkersHave = pPlotCity->AI_getWorkersHave();
+ int iWorkersNeeded = pPlotCity->AI_getWorkersNeeded();
+ szString.append(CvWString::format(L"\n\nWorkers H/N (%d , %d)", iWorkersHave, iWorkersNeeded));
+
+ int iWorkBoatsNeeded = pPlotCity->AI_neededSeaWorkers();
+ szString.append(CvWString::format(L"\n\nWorkboats Needed = %d", iWorkBoatsNeeded));
+
+ int iAreaSiteBestValue = 0;
+ int iNumAreaCitySites = kPlayer.AI_getNumAreaCitySites(pPlot->getArea(), iAreaSiteBestValue);
+ int iOtherSiteBestValue = 0;
+ int iNumOtherCitySites = (pPlot->waterArea() == NULL) ? 0 : kPlayer.AI_getNumAdjacentAreaCitySites(pPlot->waterArea()->getID(), pPlot->getArea(), iOtherSiteBestValue);
+
+ szString.append(CvWString::format(L"\n\nArea Sites = %d (%d)", iNumAreaCitySites, iAreaSiteBestValue));
+ szString.append(CvWString::format(L"\nOther Sites = %d (%d)", iNumOtherCitySites, iOtherSiteBestValue));
+
+
+ }
+ else if (pPlot->getOwner() != NO_PLAYER)
+ {
+ for (int iI = 0; iI < GC.getNumCivicInfos(); iI++)
+ {
+ szString.append(CvWString::format(L"\n %s = %d", GC.getCivicInfo((CivicTypes)iI).getDescription(), GET_PLAYER(pPlot->getOwner()).AI_civicValue((CivicTypes)iI)));
+ }
+ }
+ return;
+ }
+ else if (bShift && !bAlt && (gDLL->getChtLvl() > 0))
+ {
+ szString.append(GC.getTerrainInfo(pPlot->getTerrainType()).getDescription());
+
+ FAssert((0 < GC.getNumBonusInfos()) && "GC.getNumBonusInfos() is not greater than zero but an array is being allocated in CvInterface::updateHelpStrings");
+ for (iI = 0; iI < GC.getNumBonusInfos(); ++iI)
+ {
+ if (pPlot->isPlotGroupConnectedBonus(GC.getGameINLINE().getActivePlayer(), ((BonusTypes)iI)))
+ {
+ szString.append(NEWLINE);
+ szString.append(GC.getBonusInfo((BonusTypes)iI).getDescription());
+ szString.append(CvWString::format(L" (%d)", GET_PLAYER(GC.getGameINLINE().getActivePlayer()).AI_bonusVal((BonusTypes)iI)));
+ }
+ }
+
+ if (pPlot->getPlotGroup(GC.getGameINLINE().getActivePlayer()) != NULL)
+ {
+ szTempBuffer.Format(L"\n(%d, %d) group: %d", pPlot->getX_INLINE(), pPlot->getY_INLINE(), pPlot->getPlotGroup(GC.getGameINLINE().getActivePlayer())->getID());
+ }
+ else
+ {
+ szTempBuffer.Format(L"\n(%d, %d) group: (-1, -1)", pPlot->getX_INLINE(), pPlot->getY_INLINE());
+ }
+ szString.append(szTempBuffer);
+
+ szTempBuffer.Format(L"\nArea: %d", pPlot->getArea());
+ szString.append(szTempBuffer);
+
+ char tempChar = 'x';
+ if(pPlot->getRiverNSDirection() == CARDINALDIRECTION_NORTH)
+ {
+ tempChar = 'N';
+ }
+ else if(pPlot->getRiverNSDirection() == CARDINALDIRECTION_SOUTH)
+ {
+ tempChar = 'S';
+ }
+ szTempBuffer.Format(L"\nNSRiverFlow: %c", tempChar);
+ szString.append(szTempBuffer);
+
+ tempChar = 'x';
+ if(pPlot->getRiverWEDirection() == CARDINALDIRECTION_WEST)
+ {
+ tempChar = 'W';
+ }
+ else if(pPlot->getRiverWEDirection() == CARDINALDIRECTION_EAST)
+ {
+ tempChar = 'E';
+ }
+ szTempBuffer.Format(L"\nWERiverFlow: %c", tempChar);
+ szString.append(szTempBuffer);
+
+ if(pPlot->getRouteType() != NO_ROUTE)
+ {
+ szTempBuffer.Format(L"\nRoute: %s", GC.getRouteInfo(pPlot->getRouteType()).getDescription());
+ szString.append(szTempBuffer);
+ }
+
+ if(pPlot->getRouteSymbol() != NULL)
+ {
+ szTempBuffer.Format(L"\nConnection: %i", gDLL->getRouteIFace()->getConnectionMask(pPlot->getRouteSymbol()));
+ szString.append(szTempBuffer);
+ }
+
+ for (iI = 0; iI < MAX_PLAYERS; ++iI)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isAlive())
+ {
+ if (pPlot->getCulture((PlayerTypes)iI) > 0)
+ {
+ szTempBuffer.Format(L"\n%s Culture: %d", GET_PLAYER((PlayerTypes)iI).getName(), pPlot->getCulture((PlayerTypes)iI));
+ szString.append(szTempBuffer);
+ }
+ }
+ }
+
+ PlayerTypes eActivePlayer = GC.getGameINLINE().getActivePlayer();
+ int iActualFoundValue = pPlot->getFoundValue(eActivePlayer);
+ int iCalcFoundValue = GET_PLAYER(eActivePlayer).AI_foundValue(pPlot->getX_INLINE(), pPlot->getY_INLINE(), -1, false);
+ int iStartingFoundValue = GET_PLAYER(eActivePlayer).AI_foundValue(pPlot->getX_INLINE(), pPlot->getY_INLINE(), -1, true);
+
+ szTempBuffer.Format(L"\nFound Value: %d, (%d, %d)", iActualFoundValue, iCalcFoundValue, iStartingFoundValue);
+ szString.append(szTempBuffer);
+
+ CvCity* pWorkingCity = pPlot->getWorkingCity();
+ if (NULL != pWorkingCity)
+ {
+ int iPlotIndex = pWorkingCity->getCityPlotIndex(pPlot);
+ int iBuildValue = pWorkingCity->AI_getBestBuildValue(iPlotIndex);
+ BuildTypes eBestBuild = pWorkingCity->AI_getBestBuild(iPlotIndex);
+
+ if (NO_BUILD != eBestBuild)
+ {
+ szTempBuffer.Format(L"\nBest Build: %s (%d)", GC.getBuildInfo(eBestBuild).getDescription(), iBuildValue);
+ szString.append(szTempBuffer);
+ }
+ }
+
+ {
+ szTempBuffer.Format(L"\nStack Str: land=%d(%d), sea=%d(%d), air=%d(%d)",
+ pPlot->AI_sumStrength(NO_PLAYER, NO_PLAYER, DOMAIN_LAND, false, false, false),
+ pPlot->AI_sumStrength(NO_PLAYER, NO_PLAYER, DOMAIN_LAND, true, false, false),
+ pPlot->AI_sumStrength(NO_PLAYER, NO_PLAYER, DOMAIN_SEA, false, false, false),
+ pPlot->AI_sumStrength(NO_PLAYER, NO_PLAYER, DOMAIN_SEA, true, false, false),
+ pPlot->AI_sumStrength(NO_PLAYER, NO_PLAYER, DOMAIN_AIR, false, false, false),
+ pPlot->AI_sumStrength(NO_PLAYER, NO_PLAYER, DOMAIN_AIR, true, false, false));
+ szString.append(szTempBuffer);
+ }
+
+ if (pPlot->getPlotCity() != NULL)
+ {
+ PlayerTypes ePlayer = pPlot->getOwnerINLINE();
+ CvPlayerAI& kPlayer = GET_PLAYER(ePlayer);
+
+ szString.append(CvWString::format(L"\n\nI spy with my little eye..."));
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); ++iI)
+ {
+ if (kPlayer.AI_getUnitClassWeight((UnitClassTypes)iI) != 0)
+ {
+ szString.append(CvWString::format(L"\n%s = %d", GC.getUnitClassInfo((UnitClassTypes)iI).getDescription(), kPlayer.AI_getUnitClassWeight((UnitClassTypes)iI)));
+ }
+ }
+ szString.append(CvWString::format(L"\n\nalso unit combat types..."));
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); ++iI)
+ {
+ if (kPlayer.AI_getUnitCombatWeight((UnitCombatTypes)iI) != 0)
+ {
+ szString.append(CvWString::format(L"\n%s = % d", GC.getUnitCombatInfo((UnitCombatTypes)iI).getDescription(), kPlayer.AI_getUnitCombatWeight((UnitCombatTypes)iI)));
+ }
+ }
+ }
+ }
+ else if (!bShift && bAlt && (gDLL->getChtLvl() > 0))
+ {
+ if (pPlot->isOwned())
+ {
+ szTempBuffer.Format(L"\nThis player has %d area cities", pPlot->area()->getCitiesPerPlayer(pPlot->getOwnerINLINE()));
+ szString.append(szTempBuffer);
+ for (int iI = 0; iI < GC.getNumReligionInfos(); ++iI)
+ {
+ int iNeededMissionaries = GET_PLAYER(pPlot->getOwnerINLINE()).AI_neededMissionaries(pPlot->area(), ((ReligionTypes)iI));
+ if (iNeededMissionaries > 0)
+ {
+ szTempBuffer.Format(L"\nNeeded %c missionaries = %d", GC.getReligionInfo((ReligionTypes)iI).getChar(), iNeededMissionaries);
+ szString.append(szTempBuffer);
+ }
+ }
+
+ int iOurDefense = GET_PLAYER(pPlot->getOwnerINLINE()).AI_getOurPlotStrength(pPlot, 0, true, false);
+ int iEnemyOffense = GET_PLAYER(pPlot->getOwnerINLINE()).AI_getEnemyPlotStrength(pPlot, 2, false, false);
+ if (iEnemyOffense > 0)
+ {
+ szString.append(CvWString::format(SETCOLR L"\nDanger: %.2f (%d/%d)" ENDCOLR, TEXT_COLOR("COLOR_NEGATIVE_TEXT"),
+ (iEnemyOffense * 1.0f) / std::max(1, iOurDefense), iEnemyOffense, iOurDefense));
+ }
+
+ CvCity* pCity = pPlot->getPlotCity();
+ if (pCity != NULL)
+ {
+ szTempBuffer.Format(L"\n\nCulture Pressure Value = %d", pCity->AI_calculateCulturePressure());
+ szString.append(szTempBuffer);
+
+ szTempBuffer.Format(L"\nWater World Percent = %d", pCity->AI_calculateWaterWorldPercent());
+ szString.append(szTempBuffer);
+
+ CvPlayerAI& kPlayer = GET_PLAYER(pCity->getOwnerINLINE());
+ int iUnitCost = kPlayer.calculateUnitCost();
+ int iTotalCosts = kPlayer.calculatePreInflatedCosts();
+ int iUnitCostPercentage = (iUnitCost * 100) / std::max(1, iTotalCosts);
+ szString.append(CvWString::format(L"\nUnit cost percentage: %d (%d / %d)", iUnitCostPercentage, iUnitCost, iTotalCosts));
+
+ szString.append(CvWString::format(L"\nUpgrade all units: %d gold", kPlayer.AI_goldToUpgradeAllUnits()));
+
+ szString.append(CvWString::format(L"\n\nRanks:"));
+ szString.append(CvWString::format(L"\nPopulation:%d", pCity->findPopulationRank()));
+
+ szString.append(CvWString::format(L"\nFood:%d(%d), ", pCity->findYieldRateRank(YIELD_FOOD), pCity->findBaseYieldRateRank(YIELD_FOOD)));
+ szString.append(CvWString::format(L"Prod:%d(%d), ", pCity->findYieldRateRank(YIELD_PRODUCTION), pCity->findBaseYieldRateRank(YIELD_PRODUCTION)));
+ szString.append(CvWString::format(L"Commerce:%d(%d)", pCity->findYieldRateRank(YIELD_COMMERCE), pCity->findBaseYieldRateRank(YIELD_COMMERCE)));
+
+ szString.append(CvWString::format(L"\nGold:%d, ", pCity->findCommerceRateRank(COMMERCE_GOLD)));
+ szString.append(CvWString::format(L"Research:%d, ", pCity->findCommerceRateRank(COMMERCE_RESEARCH)));
+ szString.append(CvWString::format(L"Culture:%d", pCity->findCommerceRateRank(COMMERCE_CULTURE)));
+ }
+ szString.append(NEWLINE);
+
+ //AI strategies
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_DAGGER))
+ {
+ szTempBuffer.Format(L"Dagger, ");
+ szString.append(szTempBuffer);
+ }
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_CULTURE1))
+ {
+ szTempBuffer.Format(L"Culture1, ");
+ szString.append(szTempBuffer);
+ }
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_CULTURE2))
+ {
+ szTempBuffer.Format(L"Culture2, ");
+ szString.append(szTempBuffer);
+ }
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_CULTURE3))
+ {
+ szTempBuffer.Format(L"Culture3, ");
+ szString.append(szTempBuffer);
+ }
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_CULTURE4))
+ {
+ szTempBuffer.Format(L"Culture4, ");
+ szString.append(szTempBuffer);
+ }
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_MISSIONARY))
+ {
+ szTempBuffer.Format(L"Missionary, ");
+ szString.append(szTempBuffer);
+ }
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_CRUSH))
+ {
+ szTempBuffer.Format(L"Crush, ");
+ szString.append(szTempBuffer);
+ }
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_PRODUCTION))
+ {
+ szTempBuffer.Format(L"Production, ");
+ szString.append(szTempBuffer);
+ }
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_PEACE))
+ {
+ szTempBuffer.Format(L"Peace, ");
+ szString.append(szTempBuffer);
+ }
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_GET_BETTER_UNITS))
+ {
+ szTempBuffer.Format(L"GetBetterUnits, ");
+ szString.append(szTempBuffer);
+ }
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_FASTMOVERS))
+ {
+ szTempBuffer.Format(L"FastMovers, ");
+ szString.append(szTempBuffer);
+ }
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_LAND_BLITZ))
+ {
+ szTempBuffer.Format(L"LandBlitz, ");
+ szString.append(szTempBuffer);
+ }
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_AIR_BLITZ))
+ {
+ szTempBuffer.Format(L"AirBlitz, ");
+ szString.append(szTempBuffer);
+ }
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_OWABWNW))
+ {
+ szTempBuffer.Format(L"OWABWNW, ");
+ szString.append(szTempBuffer);
+ }
+
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_FINAL_WAR))
+ {
+ szTempBuffer.Format(L"FinalWar, ");
+ szString.append(szTempBuffer);
+ }
+
+ if (GET_PLAYER(pPlot->getOwner()).AI_isDoStrategy(AI_STRATEGY_BIG_ESPIONAGE))
+ {
+ szTempBuffer.Format(L"BigEspionage, ");
+ szString.append(szTempBuffer);
+ }
+
+ //Area battle plans.
+ if (pPlot->area()->getAreaAIType(pPlot->getTeam()) == AREAAI_OFFENSIVE)
+ {
+ szTempBuffer.Format(L"\n Area AI = OFFENSIVE");
+ }
+ else if (pPlot->area()->getAreaAIType(pPlot->getTeam()) == AREAAI_DEFENSIVE)
+ {
+ szTempBuffer.Format(L"\n Area AI = DEFENSIVE");
+ }
+ else if (pPlot->area()->getAreaAIType(pPlot->getTeam()) == AREAAI_MASSING)
+ {
+ szTempBuffer.Format(L"\n Area AI = MASSING");
+ }
+ else if (pPlot->area()->getAreaAIType(pPlot->getTeam()) == AREAAI_ASSAULT)
+ {
+ szTempBuffer.Format(L"\n Area AI = ASSAULT");
+ }
+ else if (pPlot->area()->getAreaAIType(pPlot->getTeam()) == AREAAI_ASSAULT_MASSING)
+ {
+ szTempBuffer.Format(L"\n Area AI = ASSAULT_MASSING");
+ }
+ else if (pPlot->area()->getAreaAIType(pPlot->getTeam()) == AREAAI_NEUTRAL)
+ {
+ szTempBuffer.Format(L"\n Area AI = NEUTRAL");
+ }
+
+ szString.append(szTempBuffer);
+ }
+
+ bool bFirst = true;
+ for (iI = 0; iI < MAX_PLAYERS; ++iI)
+ {
+ PlayerTypes ePlayer = (PlayerTypes)iI;
+ CvPlayerAI& kPlayer = GET_PLAYER(ePlayer);
+
+ if (kPlayer.isAlive())
+ {
+ int iActualFoundValue = pPlot->getFoundValue(ePlayer);
+ int iCalcFoundValue = kPlayer.AI_foundValue(pPlot->getX_INLINE(), pPlot->getY_INLINE(), -1, false);
+ int iStartingFoundValue = kPlayer.AI_foundValue(pPlot->getX_INLINE(), pPlot->getY_INLINE(), -1, true);
+ int iBestAreaFoundValue = pPlot->area()->getBestFoundValue(ePlayer);
+ int iCitySiteBestValue;
+ int iNumAreaCitySites = kPlayer.AI_getNumAreaCitySites(pPlot->getArea(), iCitySiteBestValue);
+
+ if ((iActualFoundValue > 0 || iCalcFoundValue > 0 || iStartingFoundValue > 0)
+ || ((pPlot->getOwner() == iI) && (iBestAreaFoundValue > 0)))
+ {
+ if (bFirst)
+ {
+ szString.append(CvWString::format(SETCOLR L"\nFound Values:" ENDCOLR, TEXT_COLOR("COLOR_UNIT_TEXT")));
+ bFirst = false;
+ }
+
+ szString.append(NEWLINE);
+
+ bool bIsRevealed = pPlot->isRevealed(kPlayer.getTeam(), false);
+
+ szString.append(CvWString::format(SETCOLR, TEXT_COLOR(bIsRevealed ? (((iActualFoundValue > 0) && (iActualFoundValue == iBestAreaFoundValue)) ? "COLOR_UNIT_TEXT" : "COLOR_ALT_HIGHLIGHT_TEXT") : "COLOR_HIGHLIGHT_TEXT")));
+
+ if (!bIsRevealed)
+ {
+ szString.append(CvWString::format(L"("));
+ }
+
+ szString.append(CvWString::format(L"%s: %d", kPlayer.getName(), iActualFoundValue));
+
+ if (!bIsRevealed)
+ {
+ szString.append(CvWString::format(L")"));
+ }
+
+ szString.append(CvWString::format(ENDCOLR));
+
+ if (iCalcFoundValue > 0 || iStartingFoundValue > 0)
+ {
+ szTempBuffer.Format(L" (%d,%ds)", iCalcFoundValue, iStartingFoundValue);
+ szString.append(szTempBuffer);
+ }
+
+ int iDeadlockCount = kPlayer.AI_countDeadlockedBonuses(pPlot);
+ if (iDeadlockCount > 0)
+ {
+ szTempBuffer.Format(L", " SETCOLR L"d=%d" ENDCOLR, TEXT_COLOR("COLOR_NEGATIVE_TEXT"), iDeadlockCount);
+ szString.append(szTempBuffer);
+ }
+
+ if (kPlayer.AI_isPlotCitySite(pPlot))
+ {
+ szTempBuffer.Format(L", " SETCOLR L"X" ENDCOLR, TEXT_COLOR("COLOR_UNIT_TEXT"));
+ szString.append(szTempBuffer);
+ }
+
+ if ((iBestAreaFoundValue > 0) || (iNumAreaCitySites > 0))
+ {
+ int iBestFoundValue = kPlayer.findBestFoundValue();
+
+ szTempBuffer.Format(L"\n Area Best = %d, Best = %d, Sites = %d", iBestAreaFoundValue, iBestFoundValue, iNumAreaCitySites);
+ szString.append(szTempBuffer);
+ }
+ }
+ }
+ }
+ }
+ else if (bShift && bAlt && (gDLL->getChtLvl() > 0))
+ {
+ CvCity* pCity = pPlot->getWorkingCity();
+ if (pCity != NULL)
+ {
+ // some functions we want to call are not in CvCity, worse some are protected, so made us a friend
+ CvCityAI* pCityAI = static_cast(pCity);
+
+ bool bAvoidGrowth = pCity->AI_avoidGrowth();
+ bool bIgnoreGrowth = pCityAI->AI_ignoreGrowth();
+
+ // if we over the city, then do an array of all the plots
+ if (pPlot->getPlotCity() != NULL)
+ {
+
+ // check avoid growth
+ if (bAvoidGrowth || bIgnoreGrowth)
+ {
+ // red color
+ szString.append(CvWString::format(SETCOLR, TEXT_COLOR("COLOR_NEGATIVE_TEXT")));
+
+ if (bAvoidGrowth)
+ {
+ szString.append(CvWString::format(L"AvoidGrowth"));
+
+ if (bIgnoreGrowth)
+ szString.append(CvWString::format(L", "));
+ }
+
+ if (bIgnoreGrowth)
+ szString.append(CvWString::format(L"IgnoreGrowth"));
+
+ // end color
+ szString.append(CvWString::format( ENDCOLR L"\n" ));
+ }
+
+ // if control key is down, ignore food
+ bool bIgnoreFood = gDLL->ctrlKey();
+
+ // line one is: blank, 20, 9, 10, blank
+ setCityPlotYieldValueString(szString, pCity, -1, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 20, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 9, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 10, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ szString.append(L"\n");
+
+ // line two is: 19, 8, 1, 2, 11
+ setCityPlotYieldValueString(szString, pCity, 19, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 8, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 1, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 2, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 11, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ szString.append(L"\n");
+
+ // line three is: 18, 7, 0, 3, 12
+ setCityPlotYieldValueString(szString, pCity, 18, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 7, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 0, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 3, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 12, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ szString.append(L"\n");
+
+ // line four is: 17, 6, 5, 4, 13
+ setCityPlotYieldValueString(szString, pCity, 17, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 6, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 5, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 4, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 13, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ szString.append(L"\n");
+
+ // line five is: blank, 16, 15, 14, blank
+ setCityPlotYieldValueString(szString, pCity, -1, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 16, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 15, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+ setCityPlotYieldValueString(szString, pCity, 14, bAvoidGrowth, bIgnoreGrowth, bIgnoreFood);
+
+ // show specialist values too
+ for (int iI = 0; iI < GC.getNumSpecialistInfos(); ++iI)
+ {
+ int iMaxThisSpecialist = pCity->getMaxSpecialistCount((SpecialistTypes) iI);
+ int iSpecialistCount = pCity->getSpecialistCount((SpecialistTypes) iI);
+ bool bUsingSpecialist = (iSpecialistCount > 0);
+ bool bIsDefaultSpecialist = (iI == GC.getDefineINT("DEFAULT_SPECIALIST"));
+
+ // can this city have any of this specialist?
+ if (iMaxThisSpecialist > 0 || bIsDefaultSpecialist)
+ {
+ // start color
+ if (pCity->getForceSpecialistCount((SpecialistTypes) iI) > 0)
+ szString.append(CvWString::format(L"\n" SETCOLR, TEXT_COLOR("COLOR_NEGATIVE_TEXT")));
+ else if (bUsingSpecialist)
+ szString.append(CvWString::format(L"\n" SETCOLR, TEXT_COLOR("COLOR_ALT_HIGHLIGHT_TEXT")));
+ else
+ szString.append(CvWString::format(L"\n" SETCOLR, TEXT_COLOR("COLOR_HIGHLIGHT_TEXT")));
+
+ // add name
+ szString.append(GC.getSpecialistInfo((SpecialistTypes) iI).getDescription());
+
+ // end color
+ szString.append(CvWString::format( ENDCOLR ));
+
+ // add usage
+ szString.append(CvWString::format(L": (%d/%d) ", iSpecialistCount, iMaxThisSpecialist));
+
+ // add value
+ int iValue = pCityAI->AI_specialistValue(((SpecialistTypes) iI), bAvoidGrowth, /*bRemove*/ bUsingSpecialist);
+ setYieldValueString(szString, iValue, /*bActive*/ bUsingSpecialist);
+ }
+ }
+ {
+ int iFood = GET_PLAYER(pCity->getOwnerINLINE()).AI_averageYieldMultiplier(YIELD_FOOD);
+ int iHammer = GET_PLAYER(pCity->getOwnerINLINE()).AI_averageYieldMultiplier(YIELD_PRODUCTION);
+ int iCommerce = GET_PLAYER(pCity->getOwnerINLINE()).AI_averageYieldMultiplier(YIELD_COMMERCE);
+
+ szString.append(CvWString::format(L"\nPlayer:(f%d, h%d, c%d)", iFood, iHammer, iCommerce));
+
+ iFood = pCity->AI_yieldMultiplier(YIELD_FOOD);
+ iHammer = pCity->AI_yieldMultiplier(YIELD_PRODUCTION);
+ iCommerce = pCity->AI_yieldMultiplier(YIELD_COMMERCE);
+
+ szString.append(CvWString::format(L"\nCityBa:(f%d, h%d, c%d)", iFood, iHammer, iCommerce));
+
+ iFood = pCityAI->AI_specialYieldMultiplier(YIELD_FOOD);
+ iHammer = pCityAI->AI_specialYieldMultiplier(YIELD_PRODUCTION);
+ iCommerce = pCityAI->AI_specialYieldMultiplier(YIELD_COMMERCE);
+
+ szString.append(CvWString::format(L"\nCitySp:(f%d, h%d, c%d)", iFood, iHammer, iCommerce));
+
+ szString.append(CvWString::format(L"\nExchange"));
+ for (int iI = 0; iI < NUM_COMMERCE_TYPES; ++iI)
+ {
+ iCommerce = GET_PLAYER(pCity->getOwnerINLINE()).AI_averageCommerceExchange((CommerceTypes)iI);
+ szTempBuffer.Format(L", %d%c", iCommerce, GC.getCommerceInfo((CommerceTypes) iI).getChar());
+ szString.append(szTempBuffer);
+ }
+
+ if (GET_PLAYER(pCity->getOwnerINLINE()).AI_isFinancialTrouble())
+ {
+ szTempBuffer.Format(L"$$$!!!");
+ szString.append(szTempBuffer);
+ }
+ }
+ }
+ else
+ {
+ bool bWorkingPlot = pCity->isWorkingPlot(pPlot);
+
+ if (bWorkingPlot)
+ szTempBuffer.Format( SETCOLR L"%s is working" ENDCOLR, TEXT_COLOR("COLOR_ALT_HIGHLIGHT_TEXT"), pCity->getName().GetCString());
+ else
+ szTempBuffer.Format( SETCOLR L"%s not working" ENDCOLR, TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), pCity->getName().GetCString());
+ szString.append(szTempBuffer);
+
+ int iValue = pCityAI->AI_plotValue(pPlot, bAvoidGrowth, /*bRemove*/ bWorkingPlot, /*bIgnoreFood*/ false, bIgnoreGrowth);
+ int iJuggleValue = pCityAI->AI_plotValue(pPlot, bAvoidGrowth, /*bRemove*/ bWorkingPlot, false, bIgnoreGrowth, true);
+ int iMagicValue = pCityAI->AI_getPlotMagicValue(pPlot, pCityAI->healthRate() == 0);
+
+ szTempBuffer.Format(L"\nvalue = %d\njuggle value = %d\nmagic value = %d", iValue, iJuggleValue, iMagicValue);
+ szString.append(szTempBuffer);
+ }
+ }
+
+ // calc some bonus info
+ if (GC.getGameINLINE().isDebugMode())
+ {
+ eBonus = pPlot->getBonusType();
+ }
+ else
+ {
+ eBonus = pPlot->getBonusType(GC.getGameINLINE().getActiveTeam());
+ }
+ if (eBonus != NO_BONUS)
+ {
+ szString.append(CvWString::format(L"\n%s values:", GC.getBonusInfo(eBonus).getDescription()));
+
+ for (int iPlayerIndex = 0; iPlayerIndex < MAX_PLAYERS; iPlayerIndex++)
+ {
+ CvPlayerAI& kLoopPlayer = GET_PLAYER((PlayerTypes) iPlayerIndex);
+ if (kLoopPlayer.isAlive())
+ {
+ szString.append(CvWString::format(L"\n %s: %d", kLoopPlayer.getName(), kLoopPlayer.AI_bonusVal(eBonus)));
+ }
+ }
+ }
+ }
+ else
+ {
+ eRevealOwner = pPlot->getRevealedOwner(GC.getGameINLINE().getActiveTeam(), true);
+
+ if (eRevealOwner != NO_PLAYER)
+ {
+ if (pPlot->isActiveVisible(true))
+ {
+ szTempBuffer.Format(L"%d%% " SETCOLR L"%s" ENDCOLR, pPlot->calculateCulturePercent(eRevealOwner), GET_PLAYER(eRevealOwner).getPlayerTextColorR(), GET_PLAYER(eRevealOwner).getPlayerTextColorG(), GET_PLAYER(eRevealOwner).getPlayerTextColorB(), GET_PLAYER(eRevealOwner).getPlayerTextColorA(), GET_PLAYER(eRevealOwner).getCivilizationAdjective());
+ szString.append(szTempBuffer);
+ szString.append(NEWLINE);
+
+ for (int iPlayer = 0; iPlayer < MAX_PLAYERS; ++iPlayer)
+ {
+ if (iPlayer != eRevealOwner)
+ {
+ CvPlayer& kPlayer = GET_PLAYER((PlayerTypes)iPlayer);
+ if (kPlayer.isAlive() && pPlot->getCulture((PlayerTypes)iPlayer) > 0)
+ {
+ szTempBuffer.Format(L"%d%% " SETCOLR L"%s" ENDCOLR, pPlot->calculateCulturePercent((PlayerTypes)iPlayer), kPlayer.getPlayerTextColorR(), kPlayer.getPlayerTextColorG(), kPlayer.getPlayerTextColorB(), kPlayer.getPlayerTextColorA(), kPlayer.getCivilizationAdjective());
+ szString.append(szTempBuffer);
+ szString.append(NEWLINE);
+ }
+ }
+ }
+
+ }
+ else
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, GET_PLAYER(eRevealOwner).getPlayerTextColorR(), GET_PLAYER(eRevealOwner).getPlayerTextColorG(), GET_PLAYER(eRevealOwner).getPlayerTextColorB(), GET_PLAYER(eRevealOwner).getPlayerTextColorA(), GET_PLAYER(eRevealOwner).getCivilizationDescription());
+ szString.append(szTempBuffer);
+ szString.append(NEWLINE);
+ }
+ }
+
+ iDefenseModifier = pPlot->defenseModifier((eRevealOwner != NO_PLAYER ? GET_PLAYER(eRevealOwner).getTeam() : NO_TEAM), true, true);
+
+ if (iDefenseModifier != 0)
+ {
+ szString.append(gDLL->getText("TXT_KEY_PLOT_BONUS", iDefenseModifier));
+ szString.append(NEWLINE);
+ }
+
+ if (pPlot->getTerrainType() != NO_TERRAIN)
+ {
+ if (pPlot->isPeak())
+ {
+ szString.append(gDLL->getText("TXT_KEY_PLOT_PEAK"));
+ }
+ else
+ {
+ if (pPlot->isWater())
+ {
+ szTempBuffer.Format(SETCOLR, TEXT_COLOR("COLOR_WATER_TEXT"));
+ szString.append(szTempBuffer);
+ }
+
+ if (pPlot->isHills())
+ {
+ szString.append(gDLL->getText("TXT_KEY_PLOT_HILLS"));
+ }
+
+ if (pPlot->getFeatureType() != NO_FEATURE)
+ {
+ szTempBuffer.Format(L"%s/", GC.getFeatureInfo(pPlot->getFeatureType()).getDescription());
+ szString.append(szTempBuffer);
+ }
+
+ szString.append(GC.getTerrainInfo(pPlot->getTerrainType()).getDescription());
+
+ if (pPlot->isWater())
+ {
+ szString.append(ENDCOLR);
+ }
+ }
+ }
+
+ if (pPlot->hasYield())
+ {
+ for (iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ iYield = pPlot->calculateYield(((YieldTypes)iI), true);
+
+ if (iYield != 0)
+ {
+ szTempBuffer.Format(L", %d%c", iYield, GC.getYieldInfo((YieldTypes) iI).getChar());
+ szString.append(szTempBuffer);
+ }
+ }
+ }
+
+ if (pPlot->isFreshWater())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PLOT_FRESH_WATER"));
+ }
+
+ if (pPlot->isLake())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PLOT_FRESH_WATER_LAKE"));
+ }
+
+ if (pPlot->isImpassable())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PLOT_IMPASSABLE"));
+ }
+
+ if (GC.getGameINLINE().isDebugMode())
+ {
+ eBonus = pPlot->getBonusType();
+ }
+ else
+ {
+ eBonus = pPlot->getBonusType(GC.getGameINLINE().getActiveTeam());
+ }
+
+ if (eBonus != NO_BONUS)
+ {
+ szTempBuffer.Format(L"%c " SETCOLR L"%s" ENDCOLR, GC.getBonusInfo(eBonus).getChar(), TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), GC.getBonusInfo(eBonus).getDescription());
+ szString.append(NEWLINE);
+ szString.append(szTempBuffer);
+
+ if (GC.getBonusInfo(eBonus).getHealth() != 0)
+ {
+ szTempBuffer.Format(L", +%d%c", abs(GC.getBonusInfo(eBonus).getHealth()), ((GC.getBonusInfo(eBonus).getHealth() > 0) ? gDLL->getSymbolID(HEALTHY_CHAR): gDLL->getSymbolID(UNHEALTHY_CHAR)));
+ szString.append(szTempBuffer);
+ }
+
+ if (GC.getBonusInfo(eBonus).getHappiness() != 0)
+ {
+ szTempBuffer.Format(L", +%d%c", abs(GC.getBonusInfo(eBonus).getHappiness()), ((GC.getBonusInfo(eBonus).getHappiness() > 0) ? gDLL->getSymbolID(HAPPY_CHAR): gDLL->getSymbolID(UNHAPPY_CHAR)));
+ szString.append(szTempBuffer);
+ }
+
+ if ((pPlot->getImprovementType() == NO_IMPROVEMENT) || !(GC.getImprovementInfo(pPlot->getImprovementType()).isImprovementBonusTrade(eBonus)))
+ {
+ if (!(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isHasTech((TechTypes)GC.getBonusInfo(eBonus).getTechCityTrade())))
+ {
+ szString.append(gDLL->getText("TXT_KEY_PLOT_RESEARCH", GC.getTechInfo((TechTypes) GC.getBonusInfo(eBonus).getTechCityTrade()).getTextKeyWide()));
+ }
+
+ if (!pPlot->isCity())
+ {
+ for (iI = 0; iI < GC.getNumBuildInfos(); ++iI)
+ {
+ if (GC.getBuildInfo((BuildTypes) iI).getImprovement() != NO_IMPROVEMENT)
+ {
+ CvImprovementInfo& kImprovementInfo = GC.getImprovementInfo((ImprovementTypes) GC.getBuildInfo((BuildTypes) iI).getImprovement());
+ if (kImprovementInfo.isImprovementBonusTrade(eBonus))
+ {
+ if (pPlot->canHaveImprovement(((ImprovementTypes)(GC.getBuildInfo((BuildTypes) iI).getImprovement())), GC.getGameINLINE().getActiveTeam(), true))
+ {
+ if (GET_TEAM(GC.getGameINLINE().getActiveTeam()).isHasTech((TechTypes)GC.getBuildInfo((BuildTypes) iI).getTechPrereq()))
+ {
+ szString.append(gDLL->getText("TXT_KEY_PLOT_REQUIRES", kImprovementInfo.getTextKeyWide()));
+ }
+ else if (GC.getBonusInfo(eBonus).getTechCityTrade() != GC.getBuildInfo((BuildTypes) iI).getTechPrereq())
+ {
+ szString.append(gDLL->getText("TXT_KEY_PLOT_RESEARCH", GC.getTechInfo((TechTypes) GC.getBuildInfo((BuildTypes) iI).getTechPrereq()).getTextKeyWide()));
+ }
+
+ bool bFirst = true;
+
+ for (int k = 0; k < NUM_YIELD_TYPES; k++)
+ {
+ int iYieldChange = kImprovementInfo.getImprovementBonusYield(eBonus, k) + kImprovementInfo.getYieldChange(k);
+ if (iYieldChange != 0)
+ {
+ if (iYieldChange > 0)
+ {
+ szTempBuffer.Format(L"+%d%c", iYieldChange, GC.getYieldInfo((YieldTypes)k).getChar());
+ }
+ else
+ {
+ szTempBuffer.Format(L"%d%c", iYieldChange, GC.getYieldInfo((YieldTypes)k).getChar());
+ }
+ setListHelp(szString, L"\n", szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ if (!bFirst)
+ {
+ szString.append(gDLL->getText("TXT_KEY_BONUS_WITH_IMPROVEMENT", kImprovementInfo.getTextKeyWide()));
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (!(pPlot->isBonusNetwork(GC.getGameINLINE().getActiveTeam())))
+ {
+ szString.append(gDLL->getText("TXT_KEY_PLOT_REQUIRES_ROUTE"));
+ }
+
+ if (!CvWString(GC.getBonusInfo(eBonus).getHelp()).empty())
+ {
+ szString.append(NEWLINE);
+ szString.append(GC.getBonusInfo(eBonus).getHelp());
+ }
+ }
+
+ eImprovement = pPlot->getRevealedImprovementType(GC.getGameINLINE().getActiveTeam(), true);
+
+ if (eImprovement != NO_IMPROVEMENT)
+ {
+ szString.append(NEWLINE);
+ szString.append(GC.getImprovementInfo(eImprovement).getDescription());
+
+ bFound = false;
+
+ for (iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ if (GC.getImprovementInfo(eImprovement).getIrrigatedYieldChange(iI) != 0)
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+ if (bFound)
+ {
+ if (pPlot->isIrrigationAvailable())
+ {
+ szString.append(gDLL->getText("TXT_KEY_PLOT_IRRIGATED"));
+ }
+ else
+ {
+ szString.append(gDLL->getText("TXT_KEY_PLOT_NOT_IRRIGATED"));
+ }
+ }
+
+ if (GC.getImprovementInfo(eImprovement).getImprovementUpgrade() != NO_IMPROVEMENT)
+ {
+ if ((pPlot->getUpgradeProgress() > 0) || pPlot->isBeingWorked())
+ {
+ iTurns = pPlot->getUpgradeTimeLeft(eImprovement, eRevealOwner);
+
+ szString.append(gDLL->getText("TXT_KEY_PLOT_IMP_UPGRADE", iTurns, GC.getImprovementInfo((ImprovementTypes) GC.getImprovementInfo(eImprovement).getImprovementUpgrade()).getTextKeyWide()));
+ }
+ else
+ {
+ szString.append(gDLL->getText("TXT_KEY_PLOT_WORK_TO_UPGRADE", GC.getImprovementInfo((ImprovementTypes) GC.getImprovementInfo(eImprovement).getImprovementUpgrade()).getTextKeyWide()));
+ }
+ }
+ }
+
+ if (pPlot->getRevealedRouteType(GC.getGameINLINE().getActiveTeam(), true) != NO_ROUTE)
+ {
+ szString.append(NEWLINE);
+ szString.append(GC.getRouteInfo(pPlot->getRevealedRouteType(GC.getGameINLINE().getActiveTeam(), true)).getDescription());
+ }
+
+ if (pPlot->getBlockadedCount(GC.getGameINLINE().getActiveTeam()) > 0)
+ {
+ szString.append(CvWString::format(SETCOLR, TEXT_COLOR("COLOR_NEGATIVE_TEXT")));
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PLOT_BLOCKADED"));
+ szString.append(CvWString::format( ENDCOLR));
+ }
+
+ }
+
+ if (pPlot->getFeatureType() != NO_FEATURE)
+ {
+ int iDamage = GC.getFeatureInfo(pPlot->getFeatureType()).getTurnDamage();
+
+ if (iDamage > 0)
+ {
+ szString.append(CvWString::format(SETCOLR, TEXT_COLOR("COLOR_NEGATIVE_TEXT")));
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_PLOT_DAMAGE", iDamage));
+ szString.append(CvWString::format( ENDCOLR));
+ }
+ }
+}
+
+
+void CvGameTextMgr::setCityPlotYieldValueString(CvWStringBuffer &szString, CvCity* pCity, int iIndex, bool bAvoidGrowth, bool bIgnoreGrowth, bool bIgnoreFood)
+{
+ PROFILE_FUNC();
+
+ CvPlot* pPlot = NULL;
+
+ if (iIndex >= 0 && iIndex < NUM_CITY_PLOTS)
+ pPlot = pCity->getCityIndexPlot(iIndex);
+
+ if (pPlot != NULL)
+ {
+ CvCityAI* pCityAI = static_cast(pCity);
+ bool bWorkingPlot = pCity->isWorkingPlot(iIndex);
+
+ int iValue = pCityAI->AI_plotValue(pPlot, bAvoidGrowth, /*bRemove*/ bWorkingPlot, bIgnoreFood, bIgnoreGrowth);
+
+ setYieldValueString(szString, iValue, /*bActive*/ bWorkingPlot);
+ }
+ else
+ setYieldValueString(szString, 0, /*bActive*/ false, /*bMakeWhitespace*/ true);
+}
+
+void CvGameTextMgr::setYieldValueString(CvWStringBuffer &szString, int iValue, bool bActive, bool bMakeWhitespace)
+{
+ PROFILE_FUNC();
+
+ static bool bUseFloats = false;
+
+ if (bActive)
+ szString.append(CvWString::format(SETCOLR, TEXT_COLOR("COLOR_ALT_HIGHLIGHT_TEXT")));
+ else
+ szString.append(CvWString::format(SETCOLR, TEXT_COLOR("COLOR_HIGHLIGHT_TEXT")));
+
+ if (!bMakeWhitespace)
+ {
+ if (bUseFloats)
+ {
+ float fValue = ((float) iValue) / 10000;
+ szString.append(CvWString::format(L"%2.3f " ENDCOLR, fValue));
+ }
+ else
+ szString.append(CvWString::format(L"%04d " ENDCOLR, iValue/10));
+ }
+ else
+ szString.append(CvWString::format(L" " ENDCOLR));
+}
+
+void CvGameTextMgr::setCityBarHelp(CvWStringBuffer &szString, CvCity* pCity)
+{
+ PROFILE_FUNC();
+
+ CvWString szTempBuffer;
+ bool bFirst;
+ int iFoodDifference;
+ int iProductionDiffNoFood;
+ int iProductionDiffJustFood;
+ int iRate;
+ int iI;
+
+ iFoodDifference = pCity->foodDifference();
+
+ szString.append(pCity->getName());
+
+ if (iFoodDifference <= 0)
+ {
+ szString.append(gDLL->getText("TXT_KEY_CITY_BAR_GROWTH", pCity->getFood(), pCity->growthThreshold()));
+ }
+ else
+ {
+ szString.append(gDLL->getText("TXT_KEY_CITY_BAR_FOOD_GROWTH", iFoodDifference, pCity->getFood(), pCity->growthThreshold(), pCity->getFoodTurnsLeft()));
+ }
+ if (pCity->getProductionNeeded() != MAX_INT)
+ {
+ iProductionDiffNoFood = pCity->getCurrentProductionDifference(true, true);
+ iProductionDiffJustFood = (pCity->getCurrentProductionDifference(false, true) - iProductionDiffNoFood);
+
+ if (iProductionDiffJustFood > 0)
+ {
+ szString.append(gDLL->getText("TXT_KEY_CITY_BAR_FOOD_HAMMER_PRODUCTION", iProductionDiffJustFood, iProductionDiffNoFood, pCity->getProductionName(), pCity->getProduction(), pCity->getProductionNeeded(), pCity->getProductionTurnsLeft()));
+ }
+ else if (iProductionDiffNoFood > 0)
+ {
+ szString.append(gDLL->getText("TXT_KEY_CITY_BAR_HAMMER_PRODUCTION", iProductionDiffNoFood, pCity->getProductionName(), pCity->getProduction(), pCity->getProductionNeeded(), pCity->getProductionTurnsLeft()));
+ }
+ else
+ {
+ szString.append(gDLL->getText("TXT_KEY_CITY_BAR_PRODUCTION", pCity->getProductionName(), pCity->getProduction(), pCity->getProductionNeeded()));
+ }
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; ++iI)
+ {
+ iRate = pCity->getCommerceRateTimes100((CommerceTypes)iI);
+
+ if (iRate != 0)
+ {
+ szTempBuffer.Format(L"%d.%02d %c", iRate/100, iRate%100, GC.getCommerceInfo((CommerceTypes)iI).getChar());
+ setListHelp(szString, NEWLINE, szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ iRate = pCity->getGreatPeopleRate();
+
+ if (iRate != 0)
+ {
+ szTempBuffer.Format(L"%d%c", iRate, gDLL->getSymbolID(GREAT_PEOPLE_CHAR));
+ setListHelp(szString, NEWLINE, szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+
+ if (!bFirst)
+ {
+ szString.append(gDLL->getText("TXT_KEY_PER_TURN"));
+ }
+
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("INTERFACE_CITY_MAINTENANCE"));
+ int iMaintenance = pCity->getMaintenanceTimes100();
+ szString.append(CvWString::format(L" -%d.%02d %c", iMaintenance/100, iMaintenance%100, GC.getCommerceInfo(COMMERCE_GOLD).getChar()));
+
+ bFirst = true;
+ for (iI = 0; iI < GC.getNumBuildingInfos(); ++iI)
+ {
+ if (pCity->getNumRealBuilding((BuildingTypes)iI) > 0)
+ {
+ setListHelp(szString, NEWLINE, GC.getBuildingInfo((BuildingTypes)iI).getDescription(), L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ if (pCity->getCultureLevel() != NO_CULTURELEVEL)
+ {
+ szString.append(gDLL->getText("TXT_KEY_CITY_BAR_CULTURE", pCity->getCulture(pCity->getOwnerINLINE()), pCity->getCultureThreshold(), GC.getCultureLevelInfo(pCity->getCultureLevel()).getTextKeyWide()));
+ }
+
+ if (pCity->getGreatPeopleProgress() > 0)
+ {
+ szString.append(gDLL->getText("TXT_KEY_CITY_BAR_GREAT_PEOPLE", pCity->getGreatPeopleProgress(), GET_PLAYER(pCity->getOwnerINLINE()).greatPeopleThreshold(false)));
+ }
+
+ int iNumUnits = pCity->plot()->countNumAirUnits(GC.getGameINLINE().getActiveTeam());
+ if (pCity->getAirUnitCapacity(GC.getGameINLINE().getActiveTeam()) > 0 && iNumUnits > 0)
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText("TXT_KEY_CITY_BAR_AIR_UNIT_CAPACITY", iNumUnits, pCity->getAirUnitCapacity(GC.getGameINLINE().getActiveTeam())));
+ }
+
+ szString.append(NEWLINE);
+
+ szString.append(gDLL->getText("TXT_KEY_CITY_BAR_SELECT", pCity->getNameKey()));
+ szString.append(gDLL->getText("TXT_KEY_CITY_BAR_SELECT_CTRL"));
+ szString.append(gDLL->getText("TXT_KEY_CITY_BAR_SELECT_ALT"));
+}
+
+
+void CvGameTextMgr::parseTraits(CvWStringBuffer &szHelpString, TraitTypes eTrait, CivilizationTypes eCivilization, bool bDawnOfMan)
+{
+ PROFILE_FUNC();
+
+ CvWString szTempBuffer;
+ BuildingTypes eLoopBuilding;
+ UnitTypes eLoopUnit;
+ int iLast;
+ int iI, iJ;
+ CvWString szText;
+
+ // Trait Name
+ szText = GC.getTraitInfo(eTrait).getDescription();
+ if (bDawnOfMan)
+ {
+ szTempBuffer.Format(L"%s", szText.GetCString());
+ }
+ else
+ {
+ szTempBuffer.Format(NEWLINE SETCOLR L"%s" ENDCOLR, TEXT_COLOR("COLOR_ALT_HIGHLIGHT_TEXT"), szText.GetCString());
+ }
+ szHelpString.append(szTempBuffer);
+
+ if (!bDawnOfMan)
+ {
+ if (!CvWString(GC.getTraitInfo(eTrait).getHelp()).empty())
+ {
+ szHelpString.append(GC.getTraitInfo(eTrait).getHelp());
+ }
+
+ // iHealth
+ if (GC.getTraitInfo(eTrait).getHealth() != 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_HEALTH", GC.getTraitInfo(eTrait).getHealth()));
+ }
+
+ // iHappiness
+ if (GC.getTraitInfo(eTrait).getHappiness() != 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_HAPPINESS", GC.getTraitInfo(eTrait).getHappiness()));
+ }
+
+ // iMaxAnarchy
+ if (GC.getTraitInfo(eTrait).getMaxAnarchy() != -1)
+ {
+ if (GC.getTraitInfo(eTrait).getMaxAnarchy() == 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_NO_ANARCHY"));
+ }
+ else
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_MAX_ANARCHY", GC.getTraitInfo(eTrait).getMaxAnarchy()));
+ }
+ }
+
+ // iUpkeepModifier
+ if (GC.getTraitInfo(eTrait).getUpkeepModifier() != 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_CIVIC_UPKEEP_MODIFIER", GC.getTraitInfo(eTrait).getUpkeepModifier()));
+ }
+
+ // AGDM addition: Describe effect of iCityUpkeepModifier tag introduced by T-Hawk for RB Mod
+ if (GC.getTraitInfo(eTrait).getCityUpkeepModifier() != 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_CITY_UPKEEP_MODIFIER", 0 - GC.getTraitInfo(eTrait).getCityUpkeepModifier()));
+ }
+
+ // iLevelExperienceModifier
+ if (GC.getTraitInfo(eTrait).getLevelExperienceModifier() != 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_CIVIC_LEVEL_MODIFIER", GC.getTraitInfo(eTrait).getLevelExperienceModifier()));
+ }
+
+ // iGreatPeopleRateModifier
+ if (GC.getTraitInfo(eTrait).getGreatPeopleRateModifier() != 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_GREAT_PEOPLE_MODIFIER", GC.getTraitInfo(eTrait).getGreatPeopleRateModifier()));
+ }
+
+ // iGreatGeneralRateModifier
+ if (GC.getTraitInfo(eTrait).getGreatGeneralRateModifier() != 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_GREAT_GENERAL_MODIFIER", GC.getTraitInfo(eTrait).getGreatGeneralRateModifier()));
+ }
+
+ if (GC.getTraitInfo(eTrait).getDomesticGreatGeneralRateModifier() != 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_DOMESTIC_GREAT_GENERAL_MODIFIER", GC.getTraitInfo(eTrait).getDomesticGreatGeneralRateModifier()));
+ }
+
+ // Wonder Production Effects
+ if ((GC.getTraitInfo(eTrait).getMaxGlobalBuildingProductionModifier() != 0)
+ || (GC.getTraitInfo(eTrait).getMaxTeamBuildingProductionModifier() != 0)
+ || (GC.getTraitInfo(eTrait).getMaxPlayerBuildingProductionModifier() != 0))
+ {
+ if ((GC.getTraitInfo(eTrait).getMaxGlobalBuildingProductionModifier() == GC.getTraitInfo(eTrait).getMaxTeamBuildingProductionModifier())
+ && (GC.getTraitInfo(eTrait).getMaxGlobalBuildingProductionModifier() == GC.getTraitInfo(eTrait).getMaxPlayerBuildingProductionModifier()))
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_WONDER_PRODUCTION_MODIFIER", GC.getTraitInfo(eTrait).getMaxGlobalBuildingProductionModifier()));
+ }
+ else
+ {
+ if (GC.getTraitInfo(eTrait).getMaxGlobalBuildingProductionModifier() != 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_WORLD_WONDER_PRODUCTION_MODIFIER", GC.getTraitInfo(eTrait).getMaxGlobalBuildingProductionModifier()));
+ }
+
+ if (GC.getTraitInfo(eTrait).getMaxTeamBuildingProductionModifier() != 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_TEAM_WONDER_PRODUCTION_MODIFIER", GC.getTraitInfo(eTrait).getMaxTeamBuildingProductionModifier()));
+ }
+
+ if (GC.getTraitInfo(eTrait).getMaxPlayerBuildingProductionModifier() != 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_NATIONAL_WONDER_PRODUCTION_MODIFIER", GC.getTraitInfo(eTrait).getMaxPlayerBuildingProductionModifier()));
+ }
+ }
+ }
+
+ // ExtraYieldThresholds
+ for (iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ if (GC.getTraitInfo(eTrait).getExtraYieldThreshold(iI) > 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_EXTRA_YIELD_THRESHOLDS", GC.getYieldInfo((YieldTypes) iI).getChar(), GC.getTraitInfo(eTrait).getExtraYieldThreshold(iI), GC.getYieldInfo((YieldTypes) iI).getChar()));
+ }
+ // Trade Yield Modifiers
+ if (GC.getTraitInfo(eTrait).getTradeYieldModifier(iI) != 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_TRADE_YIELD_MODIFIERS", GC.getTraitInfo(eTrait).getTradeYieldModifier(iI), GC.getYieldInfo((YieldTypes) iI).getChar(), "YIELD"));
+ }
+ }
+
+ // CommerceChanges
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; ++iI)
+ {
+ if (GC.getTraitInfo(eTrait).getCommerceChange(iI) != 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_COMMERCE_CHANGES", GC.getTraitInfo(eTrait).getCommerceChange(iI), GC.getCommerceInfo((CommerceTypes) iI).getChar(), "COMMERCE"));
+ }
+
+ if (GC.getTraitInfo(eTrait).getCommerceModifier(iI) != 0)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_COMMERCE_MODIFIERS", GC.getTraitInfo(eTrait).getCommerceModifier(iI), GC.getCommerceInfo((CommerceTypes) iI).getChar(), "COMMERCE"));
+ }
+ }
+
+ // Free Promotions
+ bool bFoundPromotion = false;
+ szTempBuffer.clear();
+ for (iI = 0; iI < GC.getNumPromotionInfos(); ++iI)
+ {
+ if (GC.getTraitInfo(eTrait).isFreePromotion(iI))
+ {
+ if (bFoundPromotion)
+ {
+ szTempBuffer += L", ";
+ }
+
+ szTempBuffer += CvWString::format(L"%s", GC.getPromotionInfo((PromotionTypes) iI).getDescription());
+ bFoundPromotion = true;
+ }
+ }
+
+ if (bFoundPromotion)
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_FREE_PROMOTIONS", szTempBuffer.GetCString()));
+
+ for (iJ = 0; iJ < GC.getNumUnitCombatInfos(); iJ++)
+ {
+ if (GC.getTraitInfo(eTrait).isFreePromotionUnitCombat(iJ))
+ {
+ szTempBuffer.Format(L"\n %c%s", gDLL->getSymbolID(BULLET_CHAR), GC.getUnitCombatInfo((UnitCombatTypes)iJ).getDescription());
+ szHelpString.append(szTempBuffer);
+ }
+ }
+ }
+
+ // No Civic Maintenance
+ for (iI = 0; iI < GC.getNumCivicOptionInfos(); ++iI)
+ {
+ if (GC.getCivicOptionInfo((CivicOptionTypes) iI).getTraitNoUpkeep(eTrait))
+ {
+ szHelpString.append(gDLL->getText("TXT_KEY_TRAIT_NO_UPKEEP", GC.getCivicOptionInfo((CivicOptionTypes)iI).getTextKeyWide()));
+ }
+ }
+
+ // Increase Building/Unit Production Speeds
+ iLast = 0;
+ for (iI = 0; iI < GC.getNumSpecialUnitInfos(); ++iI)
+ {
+ if (GC.getSpecialUnitInfo((SpecialUnitTypes) iI).getProductionTraits(eTrait) != 0)
+ {
+ if (GC.getSpecialUnitInfo((SpecialUnitTypes) iI).getProductionTraits(eTrait) == 100)
+ {
+ szText = gDLL->getText("TXT_KEY_TRAIT_DOUBLE_SPEED");
+ }
+ else
+ {
+ szText = gDLL->getText("TXT_KEY_TRAIT_PRODUCTION_MODIFIER", GC.getSpecialUnitInfo((SpecialUnitTypes) iI).getProductionTraits(eTrait));
+ }
+ setListHelp(szHelpString, szText.GetCString(), GC.getSpecialUnitInfo((SpecialUnitTypes) iI).getDescription(), L", ", (GC.getSpecialUnitInfo((SpecialUnitTypes) iI).getProductionTraits(eTrait) != iLast));
+ iLast = GC.getSpecialUnitInfo((SpecialUnitTypes) iI).getProductionTraits(eTrait);
+ }
+ }
+
+ // Unit Classes
+ iLast = 0;
+ for (iI = 0; iI < GC.getNumUnitClassInfos();++iI)
+ {
+ if (eCivilization == NO_CIVILIZATION)
+ {
+ eLoopUnit = ((UnitTypes)(GC.getUnitClassInfo((UnitClassTypes)iI).getDefaultUnitIndex()));
+ }
+ else
+ {
+ eLoopUnit = ((UnitTypes)(GC.getCivilizationInfo(eCivilization).getCivilizationUnits(iI)));
+ }
+
+ if (eLoopUnit != NO_UNIT && !isWorldUnitClass((UnitClassTypes)iI))
+ {
+ if (GC.getUnitInfo(eLoopUnit).getProductionTraits(eTrait) != 0)
+ {
+ if (GC.getUnitInfo(eLoopUnit).getProductionTraits(eTrait) == 100)
+ {
+ szText = gDLL->getText("TXT_KEY_TRAIT_DOUBLE_SPEED");
+ }
+ else
+ {
+ szText = gDLL->getText("TXT_KEY_TRAIT_PRODUCTION_MODIFIER", GC.getUnitInfo(eLoopUnit).getProductionTraits(eTrait));
+ }
+ CvWString szUnit;
+ szUnit.Format(L"%s", GC.getUnitInfo(eLoopUnit).getDescription());
+ setListHelp(szHelpString, szText.GetCString(), szUnit, L", ", (GC.getUnitInfo(eLoopUnit).getProductionTraits(eTrait) != iLast));
+ iLast = GC.getUnitInfo(eLoopUnit).getProductionTraits(eTrait);
+ }
+ }
+ }
+
+ // SpecialBuildings
+ iLast = 0;
+ for (iI = 0; iI < GC.getNumSpecialBuildingInfos(); ++iI)
+ {
+ if (GC.getSpecialBuildingInfo((SpecialBuildingTypes) iI).getProductionTraits(eTrait) != 0)
+ {
+ if (GC.getSpecialBuildingInfo((SpecialBuildingTypes) iI).getProductionTraits(eTrait) == 100)
+ {
+ szText = gDLL->getText("TXT_KEY_TRAIT_DOUBLE_SPEED");
+ }
+ else
+ {
+ szText = gDLL->getText("TXT_KEY_TRAIT_PRODUCTION_MODIFIER", GC.getSpecialBuildingInfo((SpecialBuildingTypes) iI).getProductionTraits(eTrait));
+ }
+ setListHelp(szHelpString, szText.GetCString(), GC.getSpecialBuildingInfo((SpecialBuildingTypes) iI).getDescription(), L", ", (GC.getSpecialBuildingInfo((SpecialBuildingTypes) iI).getProductionTraits(eTrait) != iLast));
+ iLast = GC.getSpecialBuildingInfo((SpecialBuildingTypes) iI).getProductionTraits(eTrait);
+ }
+ }
+
+ // Buildings
+ iLast = 0;
+ for (iI = 0; iI < GC.getNumBuildingClassInfos(); ++iI)
+ {
+ if (eCivilization == NO_CIVILIZATION)
+ {
+ eLoopBuilding = ((BuildingTypes)(GC.getBuildingClassInfo((BuildingClassTypes)iI).getDefaultBuildingIndex()));
+ }
+ else
+ {
+ eLoopBuilding = ((BuildingTypes)(GC.getCivilizationInfo(eCivilization).getCivilizationBuildings(iI)));
+ }
+
+ if (eLoopBuilding != NO_BUILDING && !isWorldWonderClass((BuildingClassTypes)iI))
+ {
+ if (GC.getBuildingInfo(eLoopBuilding).getProductionTraits(eTrait) != 0)
+ {
+ if (GC.getBuildingInfo(eLoopBuilding).getProductionTraits(eTrait) == 100)
+ {
+ szText = gDLL->getText("TXT_KEY_TRAIT_DOUBLE_SPEED");
+ }
+ else
+ {
+ szText = gDLL->getText("TXT_KEY_TRAIT_PRODUCTION_MODIFIER", GC.getBuildingInfo(eLoopBuilding).getProductionTraits(eTrait));
+ }
+
+ CvWString szBuilding;
+ szBuilding.Format(L"%s", GC.getBuildingInfo(eLoopBuilding).getDescription());
+ setListHelp(szHelpString, szText.GetCString(), szBuilding, L", ", (GC.getBuildingInfo(eLoopBuilding).getProductionTraits(eTrait) != iLast));
+ iLast = GC.getBuildingInfo(eLoopBuilding).getProductionTraits(eTrait);
+ }
+ }
+ }
+
+ // Buildings
+ iLast = 0;
+ for (iI = 0; iI < GC.getNumBuildingClassInfos(); ++iI)
+ {
+ if (eCivilization == NO_CIVILIZATION)
+ {
+ eLoopBuilding = ((BuildingTypes)(GC.getBuildingClassInfo((BuildingClassTypes)iI).getDefaultBuildingIndex()));
+ }
+ else
+ {
+ eLoopBuilding = ((BuildingTypes)(GC.getCivilizationInfo(eCivilization).getCivilizationBuildings(iI)));
+ }
+
+ if (eLoopBuilding != NO_BUILDING && !isWorldWonderClass((BuildingClassTypes)iI))
+ {
+ int iHappiness = GC.getBuildingInfo(eLoopBuilding).getHappinessTraits(eTrait);
+ if (iHappiness != 0)
+ {
+ if (iHappiness > 0)
+ {
+ szText = gDLL->getText("TXT_KEY_TRAIT_BUILDING_HAPPINESS", iHappiness, gDLL->getSymbolID(HAPPY_CHAR));
+ }
+ else
+ {
+ szText = gDLL->getText("TXT_KEY_TRAIT_BUILDING_HAPPINESS", -iHappiness, gDLL->getSymbolID(UNHAPPY_CHAR));
+ }
+
+ CvWString szBuilding;
+ szBuilding.Format(L"%s", GC.getBuildingInfo(eLoopBuilding).getDescription());
+ setListHelp(szHelpString, szText.GetCString(), szBuilding, L", ", (iHappiness != iLast));
+ iLast = iHappiness;
+ }
+ }
+ }
+
+ }
+
+// return szHelpString;
+}
+
+
+//
+// parseLeaderTraits - SimpleCivPicker // LOCALIZATION READY
+//
+void CvGameTextMgr::parseLeaderTraits(CvWStringBuffer &szHelpString, LeaderHeadTypes eLeader, CivilizationTypes eCivilization, bool bDawnOfMan, bool bCivilopediaText)
+{
+ PROFILE_FUNC();
+
+ CvWString szTempBuffer; // Formatting
+ int iI;
+
+ // Build help string
+ if (eLeader != NO_LEADER)
+ {
+ if (!bDawnOfMan && !bCivilopediaText)
+ {
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), GC.getLeaderHeadInfo(eLeader).getDescription());
+ szHelpString.append(szTempBuffer);
+ }
+
+ FAssert((GC.getNumTraitInfos() > 0) &&
+ "GC.getNumTraitInfos() is less than or equal to zero but is expected to be larger than zero in CvSimpleCivPicker::setLeaderText");
+
+ bool bFirst = true;
+ for (iI = 0; iI < GC.getNumTraitInfos(); ++iI)
+ {
+ if (GC.getLeaderHeadInfo(eLeader).hasTrait(iI)
+ // AGDM addition:
+ || (!bCivilopediaText && eCivilization != NO_CIVILIZATION && GC.getCivilizationInfo(eCivilization).hasTrait(iI)))
+ {
+ if (!bFirst)
+ {
+ if (bDawnOfMan)
+ {
+ szHelpString.append(L", ");
+ }
+ }
+ else
+ {
+ bFirst = false;
+ }
+ parseTraits(szHelpString, ((TraitTypes)iI), eCivilization, bDawnOfMan);
+ }
+ }
+ }
+ else
+ {
+ // Random leader
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), gDLL->getText("TXT_KEY_TRAIT_PLAYER_UNKNOWN").c_str());
+ szHelpString.append(szTempBuffer);
+ }
+
+// return szHelpString;
+}
+
+//
+// parseLeaderTraits - SimpleCivPicker // LOCALIZATION READY
+//
+void CvGameTextMgr::parseLeaderShortTraits(CvWStringBuffer &szHelpString, LeaderHeadTypes eLeader)
+{
+ PROFILE_FUNC();
+
+ int iI;
+
+ // Build help string
+ if (eLeader != NO_LEADER)
+ {
+ FAssert((GC.getNumTraitInfos() > 0) &&
+ "GC.getNumTraitInfos() is less than or equal to zero but is expected to be larger than zero in CvSimpleCivPicker::setLeaderText");
+
+ bool bFirst = true;
+ for (iI = 0; iI < GC.getNumTraitInfos(); ++iI)
+ {
+ if (GC.getLeaderHeadInfo(eLeader).hasTrait(iI))
+ {
+ if (!bFirst)
+ {
+ szHelpString.append(L"/");
+ }
+ szHelpString.append(gDLL->getText(GC.getTraitInfo((TraitTypes)iI).getShortDescription()));
+ bFirst = false;
+ }
+ }
+ }
+ else
+ {
+ // Random leader
+ szHelpString.append(CvWString("???/???"));
+ }
+
+ // return szHelpString;
+}
+
+//
+// Build Civilization Info Help Text
+//
+void CvGameTextMgr::parseCivInfos(CvWStringBuffer &szInfoText, CivilizationTypes eCivilization, bool bDawnOfMan, bool bLinks)
+{
+ PROFILE_FUNC();
+
+ CvWString szBuffer;
+ CvWString szTempString;
+ CvWString szText;
+ UnitTypes eDefaultUnit;
+ UnitTypes eUniqueUnit;
+ BuildingTypes eDefaultBuilding;
+ BuildingTypes eUniqueBuilding;
+
+ if (eCivilization != NO_CIVILIZATION)
+ {
+ if (!bDawnOfMan)
+ {
+ // Civ Name
+ szBuffer.Format(SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), GC.getCivilizationInfo(eCivilization).getDescription());
+ szInfoText.append(szBuffer);
+
+ // AGDM addition: Civilization Traits
+ bool bHasTraits = false;
+ for (int iI = 0; iI < GC.getNumTraitInfos(); ++iI)
+ {
+ if (GC.getCivilizationInfo(eCivilization).hasTrait(iI))
+ {
+ bHasTraits = true;
+ }
+ }
+ if(bHasTraits) {
+ szBuffer.Format(NEWLINE SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_ALT_HIGHLIGHT_TEXT"), gDLL->getText("TXT_KEY_PEDIA_TRAITS").GetCString());
+ szInfoText.append(szBuffer);
+ for (int iI = 0; iI < GC.getNumTraitInfos(); ++iI)
+ {
+ if (GC.getCivilizationInfo(eCivilization).hasTrait(iI))
+ {
+ // Add Trait
+ szText.Format((bLinks ? L"%s" : L"%s"), GC.getTraitInfo((TraitTypes)iI).getDescription());
+ szBuffer.Format(L"%s %c%s", NEWLINE, gDLL->getSymbolID(BULLET_CHAR), szText.GetCString());
+ szInfoText.append(szBuffer);
+ }
+ }
+ }
+ // End of AGDM addition
+
+ // Free Techs
+ szBuffer.Format(NEWLINE SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_ALT_HIGHLIGHT_TEXT"), gDLL->getText("TXT_KEY_FREE_TECHS").GetCString());
+ szInfoText.append(szBuffer);
+
+ bool bFound = false;
+ for (int iI = 0; iI < GC.getNumTechInfos(); ++iI)
+ {
+ if (GC.getCivilizationInfo(eCivilization).isCivilizationFreeTechs(iI))
+ {
+ bFound = true;
+ // Add Tech
+ szText.Format((bLinks ? L"%s" : L"%s"), GC.getTechInfo((TechTypes)iI).getDescription());
+ szBuffer.Format(L"%s %c%s", NEWLINE, gDLL->getSymbolID(BULLET_CHAR), szText.GetCString());
+ szInfoText.append(szBuffer);
+ }
+ }
+
+ if (!bFound)
+ {
+ szBuffer.Format(L"%s %s", NEWLINE, gDLL->getText("TXT_KEY_FREE_TECHS_NO").GetCString());
+ szInfoText.append(szBuffer);
+ }
+ }
+
+ // Free Units
+ szText = gDLL->getText("TXT_KEY_FREE_UNITS");
+ if (bDawnOfMan)
+ {
+ szTempString.Format(L"%s: ", szText.GetCString());
+ }
+ else
+ {
+ szTempString.Format(NEWLINE SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_ALT_HIGHLIGHT_TEXT"), szText.GetCString());
+ }
+ szInfoText.append(szTempString);
+
+ bool bFound = false;
+ for (int iI = 0; iI < GC.getNumUnitClassInfos(); ++iI)
+ {
+ eDefaultUnit = ((UnitTypes)(GC.getCivilizationInfo(eCivilization).getCivilizationUnits(iI)));
+ eUniqueUnit = ((UnitTypes)(GC.getUnitClassInfo((UnitClassTypes) iI).getDefaultUnitIndex()));
+ if ((eDefaultUnit != NO_UNIT) && (eUniqueUnit != NO_UNIT))
+ {
+ if (eDefaultUnit != eUniqueUnit)
+ {
+ // Add Unit
+ if (bDawnOfMan)
+ {
+ if (bFound)
+ {
+ szInfoText.append(L", ");
+ }
+ szBuffer.Format((bLinks ? L"%s - (%s)" : L"%s - (%s)"),
+ GC.getUnitInfo(eDefaultUnit).getDescription(),
+ GC.getUnitInfo(eUniqueUnit).getDescription());
+ }
+ else
+ {
+ szBuffer.Format(L"\n %c%s - (%s)", gDLL->getSymbolID(BULLET_CHAR),
+ GC.getUnitInfo(eDefaultUnit).getDescription(),
+ GC.getUnitInfo(eUniqueUnit).getDescription());
+ }
+ szInfoText.append(szBuffer);
+ bFound = true;
+ }
+ }
+ }
+
+ if (!bFound)
+ {
+ szText = gDLL->getText("TXT_KEY_FREE_UNITS_NO");
+ if (bDawnOfMan)
+ {
+ szTempString.Format(L"%s", szText.GetCString());
+ }
+ else
+ {
+ szTempString.Format(L"%s %s", NEWLINE, szText.GetCString());
+ }
+ szInfoText.append(szTempString);
+ bFound = true;
+ }
+
+
+ // Free Buildings
+ szText = gDLL->getText("TXT_KEY_UNIQUE_BUILDINGS");
+ if (bDawnOfMan)
+ {
+ if (bFound)
+ {
+ szInfoText.append(NEWLINE);
+ }
+ szTempString.Format(L"%s: ", szText.GetCString());
+ }
+ else
+ {
+ szTempString.Format(NEWLINE SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_ALT_HIGHLIGHT_TEXT"), szText.GetCString());
+ }
+ szInfoText.append(szTempString);
+
+ bFound = false;
+ for (int iI = 0; iI < GC.getNumBuildingClassInfos(); ++iI)
+ {
+ eDefaultBuilding = ((BuildingTypes)(GC.getCivilizationInfo(eCivilization).getCivilizationBuildings(iI)));
+ eUniqueBuilding = ((BuildingTypes)(GC.getBuildingClassInfo((BuildingClassTypes) iI).getDefaultBuildingIndex()));
+ if ((eDefaultBuilding != NO_BUILDING) && (eUniqueBuilding != NO_BUILDING))
+ {
+ if (eDefaultBuilding != eUniqueBuilding)
+ {
+ // Add Building
+ if (bDawnOfMan)
+ {
+ if (bFound)
+ {
+ szInfoText.append(L", ");
+ }
+ szBuffer.Format((bLinks ? L"%s - (%s)" : L"%s - (%s)"),
+ GC.getBuildingInfo(eDefaultBuilding).getDescription(),
+ GC.getBuildingInfo(eUniqueBuilding).getDescription());
+ }
+ else
+ {
+ szBuffer.Format(L"\n %c%s - (%s)", gDLL->getSymbolID(BULLET_CHAR),
+ GC.getBuildingInfo(eDefaultBuilding).getDescription(),
+ GC.getBuildingInfo(eUniqueBuilding).getDescription());
+ }
+ szInfoText.append(szBuffer);
+ bFound = true;
+ }
+ }
+ }
+ if (!bFound)
+ {
+ szText = gDLL->getText("TXT_KEY_UNIQUE_BUILDINGS_NO");
+ if (bDawnOfMan)
+ {
+ szTempString.Format(L"%s", szText.GetCString());
+ }
+ else
+ {
+ szTempString.Format(L"%s %s", NEWLINE, szText.GetCString());
+ }
+ szInfoText.append(szTempString);
+ }
+ }
+ else
+ {
+ // This is a random civ, let us know here...
+ szInfoText.append(gDLL->getText("TXT_KEY_CIV_UNKNOWN"));
+ }
+
+// return szInfoText;
+}
+
+
+void CvGameTextMgr::parseSpecialistHelp(CvWStringBuffer &szHelpString, SpecialistTypes eSpecialist, CvCity* pCity, bool bCivilopediaText)
+{
+ PROFILE_FUNC();
+
+ CvWString szText;
+ int aiYields[NUM_YIELD_TYPES];
+ int aiCommerces[NUM_COMMERCE_TYPES];
+ int iI;
+
+ if (eSpecialist != NO_SPECIALIST)
+ {
+ if (!bCivilopediaText)
+ {
+ szHelpString.append(GC.getSpecialistInfo(eSpecialist).getDescription());
+ }
+
+ for (iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ if (GC.getGameINLINE().getActivePlayer() == NO_PLAYER)
+ {
+ aiYields[iI] = GC.getSpecialistInfo(eSpecialist).getYieldChange(iI);
+ }
+ else
+ {
+ aiYields[iI] = GET_PLAYER((pCity != NULL) ? pCity->getOwnerINLINE() : GC.getGameINLINE().getActivePlayer()).specialistYield(eSpecialist, ((YieldTypes)iI));
+ }
+ }
+
+ setYieldChangeHelp(szHelpString, L"", L"", L"", aiYields);
+
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; ++iI)
+ {
+ if (GC.getGameINLINE().getActivePlayer() == NO_PLAYER)
+ {
+ aiCommerces[iI] = GC.getSpecialistInfo(eSpecialist).getCommerceChange(iI);
+ }
+ else
+ {
+ aiCommerces[iI] = GET_PLAYER((pCity != NULL) ? pCity->getOwnerINLINE() : GC.getGameINLINE().getActivePlayer()).specialistCommerce(((SpecialistTypes)eSpecialist), ((CommerceTypes)iI));
+ }
+ }
+
+ setCommerceChangeHelp(szHelpString, L"", L"", L"", aiCommerces);
+
+ if (GC.getSpecialistInfo(eSpecialist).getExperience() > 0)
+ {
+ szHelpString.append(NEWLINE);
+ szHelpString.append(gDLL->getText("TXT_KEY_SPECIALIST_EXPERIENCE", GC.getSpecialistInfo(eSpecialist).getExperience()));
+ }
+
+ if (GC.getSpecialistInfo(eSpecialist).getGreatPeopleRateChange() != 0)
+ {
+ szHelpString.append(NEWLINE);
+ szHelpString.append(gDLL->getText("TXT_KEY_SPECIALIST_BIRTH_RATE", GC.getSpecialistInfo(eSpecialist).getGreatPeopleRateChange()));
+ }
+
+ if (!CvWString(GC.getSpecialistInfo(eSpecialist).getHelp()).empty() && !bCivilopediaText)
+ {
+ szHelpString.append(NEWLINE);
+ szHelpString.append(GC.getSpecialistInfo(eSpecialist).getHelp());
+ }
+ }
+}
+
+void CvGameTextMgr::parseFreeSpecialistHelp(CvWStringBuffer &szHelpString, const CvCity& kCity)
+{
+ PROFILE_FUNC();
+
+ for (int iLoopSpecialist = 0; iLoopSpecialist < GC.getNumSpecialistInfos(); iLoopSpecialist++)
+ {
+ SpecialistTypes eSpecialist = (SpecialistTypes)iLoopSpecialist;
+ int iNumSpecialists = kCity.getFreeSpecialistCount(eSpecialist);
+
+ if (iNumSpecialists > 0)
+ {
+ int aiYields[NUM_YIELD_TYPES];
+ int aiCommerces[NUM_COMMERCE_TYPES];
+
+ szHelpString.append(NEWLINE);
+ szHelpString.append(CvWString::format(L"%s (%d): ", GC.getSpecialistInfo(eSpecialist).getDescription(), iNumSpecialists));
+
+ for (int iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ aiYields[iI] = iNumSpecialists * GET_PLAYER(kCity.getOwnerINLINE()).specialistYield(eSpecialist, ((YieldTypes)iI));
+ }
+
+ CvWStringBuffer szYield;
+ setYieldChangeHelp(szYield, L"", L"", L"", aiYields, false, false);
+ szHelpString.append(szYield);
+
+ for (int iI = 0; iI < NUM_COMMERCE_TYPES; ++iI)
+ {
+ aiCommerces[iI] = iNumSpecialists * GET_PLAYER(kCity.getOwnerINLINE()).specialistCommerce(eSpecialist, ((CommerceTypes)iI));
+ }
+
+ CvWStringBuffer szCommerceString;
+ setCommerceChangeHelp(szCommerceString, L"", L"", L"", aiCommerces, false, false);
+ if (!szYield.isEmpty() && !szCommerceString.isEmpty())
+ {
+ szHelpString.append(L", ");
+ }
+ szHelpString.append(szCommerceString);
+
+ if (GC.getSpecialistInfo(eSpecialist).getExperience() > 0)
+ {
+ if (!szYield.isEmpty() || !szYield.isEmpty())
+ {
+ szHelpString.append(L", ");
+ }
+ szHelpString.append(gDLL->getText("TXT_KEY_SPECIALIST_EXPERIENCE_SHORT", iNumSpecialists * GC.getSpecialistInfo(eSpecialist).getExperience()));
+ }
+ }
+ }
+}
+
+
+//
+// Promotion Help
+//
+void CvGameTextMgr::parsePromotionHelp(CvWStringBuffer &szBuffer, PromotionTypes ePromotion, const wchar* pcNewline)
+{
+ PROFILE_FUNC();
+
+ CvWString szText, szText2;
+ int iI;
+
+ if (NO_PROMOTION == ePromotion)
+ {
+ return;
+ }
+
+ if (GC.getPromotionInfo(ePromotion).isBlitz())
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_BLITZ_TEXT"));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).isAmphib())
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_AMPHIB_TEXT"));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).isRiver())
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_RIVER_ATTACK_TEXT"));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).isEnemyRoute())
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_ENEMY_ROADS_TEXT"));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).isAlwaysHeal())
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_ALWAYS_HEAL_TEXT"));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).isHillsDoubleMove())
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_HILLS_MOVE_TEXT"));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).isImmuneToFirstStrikes())
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_IMMUNE_FIRST_STRIKES_TEXT"));
+ }
+
+ for (iI = 0; iI < GC.getNumTerrainInfos(); ++iI)
+ {
+ if (GC.getPromotionInfo(ePromotion).getTerrainDoubleMove(iI))
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_DOUBLE_MOVE_TEXT", GC.getTerrainInfo((TerrainTypes) iI).getTextKeyWide()));
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumFeatureInfos(); ++iI)
+ {
+ if (GC.getPromotionInfo(ePromotion).getFeatureDoubleMove(iI))
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_DOUBLE_MOVE_TEXT", GC.getFeatureInfo((FeatureTypes) iI).getTextKeyWide()));
+ }
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getVisibilityChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_VISIBILITY_TEXT", GC.getPromotionInfo(ePromotion).getVisibilityChange()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getMovesChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_MOVE_TEXT", GC.getPromotionInfo(ePromotion).getMovesChange()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getMoveDiscountChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_MOVE_DISCOUNT_TEXT", -(GC.getPromotionInfo(ePromotion).getMoveDiscountChange())));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getAirRangeChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_AIR_RANGE_TEXT", GC.getPromotionInfo(ePromotion).getAirRangeChange()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getInterceptChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_INTERCEPT_TEXT", GC.getPromotionInfo(ePromotion).getInterceptChange()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getEvasionChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_EVASION_TEXT", GC.getPromotionInfo(ePromotion).getEvasionChange()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getWithdrawalChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_WITHDRAWAL_TEXT", GC.getPromotionInfo(ePromotion).getWithdrawalChange()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getCargoChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_CARGO_TEXT", GC.getPromotionInfo(ePromotion).getCargoChange()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getCollateralDamageChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_COLLATERAL_DAMAGE_TEXT", GC.getPromotionInfo(ePromotion).getCollateralDamageChange()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getBombardRateChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_BOMBARD_TEXT", GC.getPromotionInfo(ePromotion).getBombardRateChange()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getFirstStrikesChange() != 0)
+ {
+ if (GC.getPromotionInfo(ePromotion).getFirstStrikesChange() == 1)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_FIRST_STRIKE_TEXT", GC.getPromotionInfo(ePromotion).getFirstStrikesChange()));
+ }
+ else
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_FIRST_STRIKES_TEXT", GC.getPromotionInfo(ePromotion).getFirstStrikesChange()));
+ }
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getChanceFirstStrikesChange() != 0)
+ {
+ if (GC.getPromotionInfo(ePromotion).getChanceFirstStrikesChange() == 1)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_FIRST_STRIKE_CHANCE_TEXT", GC.getPromotionInfo(ePromotion).getChanceFirstStrikesChange()));
+ }
+ else
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_FIRST_STRIKES_CHANCE_TEXT", GC.getPromotionInfo(ePromotion).getChanceFirstStrikesChange()));
+ }
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getEnemyHealChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_HEALS_EXTRA_TEXT", GC.getPromotionInfo(ePromotion).getEnemyHealChange()) + gDLL->getText("TXT_KEY_PROMOTION_ENEMY_LANDS_TEXT"));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getNeutralHealChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_HEALS_EXTRA_TEXT", GC.getPromotionInfo(ePromotion).getNeutralHealChange()) + gDLL->getText("TXT_KEY_PROMOTION_NEUTRAL_LANDS_TEXT"));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getFriendlyHealChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_HEALS_EXTRA_TEXT", GC.getPromotionInfo(ePromotion).getFriendlyHealChange()) + gDLL->getText("TXT_KEY_PROMOTION_FRIENDLY_LANDS_TEXT"));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getSameTileHealChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_HEALS_SAME_TEXT", GC.getPromotionInfo(ePromotion).getSameTileHealChange()) + gDLL->getText("TXT_KEY_PROMOTION_DAMAGE_TURN_TEXT"));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getAdjacentTileHealChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_HEALS_ADJACENT_TEXT", GC.getPromotionInfo(ePromotion).getAdjacentTileHealChange()) + gDLL->getText("TXT_KEY_PROMOTION_DAMAGE_TURN_TEXT"));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getCombatPercent() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_STRENGTH_TEXT", GC.getPromotionInfo(ePromotion).getCombatPercent()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getCityAttackPercent() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_CITY_ATTACK_TEXT", GC.getPromotionInfo(ePromotion).getCityAttackPercent()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getCityDefensePercent() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_CITY_DEFENSE_TEXT", GC.getPromotionInfo(ePromotion).getCityDefensePercent()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getHillsAttackPercent() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_HILLS_ATTACK", GC.getPromotionInfo(ePromotion).getHillsAttackPercent()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getHillsDefensePercent() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_HILLS_DEFENSE_TEXT", GC.getPromotionInfo(ePromotion).getHillsDefensePercent()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getRevoltProtection() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_REVOLT_PROTECTION_TEXT", GC.getPromotionInfo(ePromotion).getRevoltProtection()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getCollateralDamageProtection() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_COLLATERAL_PROTECTION_TEXT", GC.getPromotionInfo(ePromotion).getCollateralDamageProtection()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getPillageChange() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_PILLAGE_CHANGE_TEXT", GC.getPromotionInfo(ePromotion).getPillageChange()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getUpgradeDiscount() != 0)
+ {
+ if (100 == GC.getPromotionInfo(ePromotion).getUpgradeDiscount())
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_UPGRADE_DISCOUNT_FREE_TEXT"));
+ }
+ else
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_UPGRADE_DISCOUNT_TEXT", GC.getPromotionInfo(ePromotion).getUpgradeDiscount()));
+ }
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getExperiencePercent() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_FASTER_EXPERIENCE_TEXT", GC.getPromotionInfo(ePromotion).getExperiencePercent()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getKamikazePercent() != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_KAMIKAZE_TEXT", GC.getPromotionInfo(ePromotion).getKamikazePercent()));
+ }
+
+ for (iI = 0; iI < GC.getNumTerrainInfos(); ++iI)
+ {
+ if (GC.getPromotionInfo(ePromotion).getTerrainAttackPercent(iI) != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_ATTACK_TEXT", GC.getPromotionInfo(ePromotion).getTerrainAttackPercent(iI), GC.getTerrainInfo((TerrainTypes) iI).getTextKeyWide()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getTerrainDefensePercent(iI) != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_DEFENSE_TEXT", GC.getPromotionInfo(ePromotion).getTerrainDefensePercent(iI), GC.getTerrainInfo((TerrainTypes) iI).getTextKeyWide()));
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumFeatureInfos(); ++iI)
+ {
+ if (GC.getPromotionInfo(ePromotion).getFeatureAttackPercent(iI) != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_ATTACK_TEXT", GC.getPromotionInfo(ePromotion).getFeatureAttackPercent(iI), GC.getFeatureInfo((FeatureTypes) iI).getTextKeyWide()));
+ }
+
+ if (GC.getPromotionInfo(ePromotion).getFeatureDefensePercent(iI) != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_DEFENSE_TEXT", GC.getPromotionInfo(ePromotion).getFeatureDefensePercent(iI), GC.getFeatureInfo((FeatureTypes) iI).getTextKeyWide()));
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); ++iI)
+ {
+ if (GC.getPromotionInfo(ePromotion).getUnitCombatModifierPercent(iI) != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_VERSUS_TEXT", GC.getPromotionInfo(ePromotion).getUnitCombatModifierPercent(iI), GC.getUnitCombatInfo((UnitCombatTypes)iI).getTextKeyWide()));
+ }
+ }
+
+ for (iI = 0; iI < NUM_DOMAIN_TYPES; ++iI)
+ {
+ if (GC.getPromotionInfo(ePromotion).getDomainModifierPercent(iI) != 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROMOTION_VERSUS_TEXT", GC.getPromotionInfo(ePromotion).getDomainModifierPercent(iI), GC.getDomainInfo((DomainTypes)iI).getTextKeyWide()));
+ }
+ }
+
+ if (wcslen(GC.getPromotionInfo(ePromotion).getHelp()) > 0)
+ {
+ szBuffer.append(pcNewline);
+ szBuffer.append(GC.getPromotionInfo(ePromotion).getHelp());
+ }
+}
+
+// Function: parseCivicInfo()
+// Description: Will parse the civic info help
+// Parameters: szHelpText -- the text to put it into
+// civicInfo - what to parse
+// Returns: nothing
+void CvGameTextMgr::parseCivicInfo(CvWStringBuffer &szHelpText, CivicTypes eCivic, bool bCivilopediaText, bool bPlayerContext, bool bSkipName)
+{
+ PROFILE_FUNC();
+
+ CvWString szFirstBuffer;
+ bool bFound;
+ bool bFirst;
+ int iLast;
+ int iI, iJ;
+
+ if (NO_CIVIC == eCivic)
+ {
+ return;
+ }
+
+ szHelpText.clear();
+
+ FAssert(GC.getGameINLINE().getActivePlayer() != NO_PLAYER || !bPlayerContext);
+
+ if (!bSkipName)
+ {
+ szHelpText.append(GC.getCivicInfo(eCivic).getDescription());
+ }
+
+ if (!bCivilopediaText)
+ {
+ if (!bPlayerContext || !(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).canDoCivics(eCivic)))
+ {
+ if (!bPlayerContext || !(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isHasTech((TechTypes)(GC.getCivicInfo(eCivic).getTechPrereq()))))
+ {
+ if (GC.getCivicInfo(eCivic).getTechPrereq() != NO_TECH)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_REQUIRES", GC.getTechInfo((TechTypes)GC.getCivicInfo(eCivic).getTechPrereq()).getTextKeyWide()));
+ }
+ }
+ }
+ }
+
+ // Special Building Not Required...
+ for (iI = 0; iI < GC.getNumSpecialBuildingInfos(); ++iI)
+ {
+ if (GC.getCivicInfo(eCivic).isSpecialBuildingNotRequired(iI))
+ {
+ // XXX "Missionaries"??? - Now in XML
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_BUILD_MISSIONARIES", GC.getSpecialBuildingInfo((SpecialBuildingTypes)iI).getTextKeyWide()));
+ }
+ }
+
+ // Valid Specialists...
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumSpecialistInfos(); ++iI)
+ {
+ if (GC.getCivicInfo(eCivic).isSpecialistValid(iI))
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_CIVIC_UNLIMTED").c_str());
+ CvWString szSpecialist;
+ szSpecialist.Format(L"%s", GC.getSpecialistInfo((SpecialistTypes)iI).getDescription());
+ setListHelp(szHelpText, szFirstBuffer, szSpecialist, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ // Great People Modifier...
+ if (GC.getCivicInfo(eCivic).getGreatPeopleRateModifier() != 0)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_GREAT_PEOPLE_MOD", GC.getCivicInfo(eCivic).getGreatPeopleRateModifier()));
+ }
+
+ // Great General Modifier...
+ if (GC.getCivicInfo(eCivic).getGreatGeneralRateModifier() != 0)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_GREAT_GENERAL_MOD", GC.getCivicInfo(eCivic).getGreatGeneralRateModifier()));
+ }
+
+ if (GC.getCivicInfo(eCivic).getDomesticGreatGeneralRateModifier() != 0)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_DOMESTIC_GREAT_GENERAL_MODIFIER", GC.getCivicInfo(eCivic).getDomesticGreatGeneralRateModifier()));
+ }
+
+ // State Religion Great People Modifier...
+ if (GC.getCivicInfo(eCivic).getStateReligionGreatPeopleRateModifier() != 0)
+ {
+ if (bPlayerContext && (GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getStateReligion() != NO_RELIGION))
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_GREAT_PEOPLE_MOD_RELIGION", GC.getCivicInfo(eCivic).getStateReligionGreatPeopleRateModifier(), GC.getReligionInfo(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getStateReligion()).getChar()));
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_GREAT_PEOPLE_MOD_STATE_RELIGION", GC.getCivicInfo(eCivic).getStateReligionGreatPeopleRateModifier(), gDLL->getSymbolID(RELIGION_CHAR)));
+ }
+ }
+
+ // Distance Maintenance Modifer...
+ if (GC.getCivicInfo(eCivic).getDistanceMaintenanceModifier() != 0)
+ {
+ if (GC.getCivicInfo(eCivic).getDistanceMaintenanceModifier() <= -100)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_DISTANCE_MAINT"));
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_DISTANCE_MAINT_MOD", GC.getCivicInfo(eCivic).getDistanceMaintenanceModifier()));
+ }
+ }
+
+ // Num Cities Maintenance Modifer...
+ if (GC.getCivicInfo(eCivic).getNumCitiesMaintenanceModifier() != 0)
+ {
+ if (GC.getCivicInfo(eCivic).getNumCitiesMaintenanceModifier() <= -100)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_NO_MAINT_NUM_CITIES"));
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_NO_MAINT_NUM_CITIES_MOD", GC.getCivicInfo(eCivic).getNumCitiesMaintenanceModifier()));
+ }
+ }
+
+ // Corporations Maintenance Modifer...
+ if (GC.getCivicInfo(eCivic).getCorporationMaintenanceModifier() != 0)
+ {
+ if (GC.getCivicInfo(eCivic).getCorporationMaintenanceModifier() <= -100)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_NO_MAINT_CORPORATION"));
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_NO_MAINT_CORPORATION_MOD", GC.getCivicInfo(eCivic).getCorporationMaintenanceModifier()));
+ }
+ }
+
+ // Extra Health
+ if (GC.getCivicInfo(eCivic).getExtraHealth() != 0)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_EXTRA_HEALTH", abs(GC.getCivicInfo(eCivic).getExtraHealth()), ((GC.getCivicInfo(eCivic).getExtraHealth() > 0) ? gDLL->getSymbolID(HEALTHY_CHAR): gDLL->getSymbolID(UNHEALTHY_CHAR))));
+ }
+
+ // Free Experience
+ if (GC.getCivicInfo(eCivic).getFreeExperience() != 0)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_FREE_XP", GC.getCivicInfo(eCivic).getFreeExperience()));
+ }
+
+ // Worker speed modifier
+ if (GC.getCivicInfo(eCivic).getWorkerSpeedModifier() != 0)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_WORKER_SPEED", GC.getCivicInfo(eCivic).getWorkerSpeedModifier()));
+ }
+
+ // Improvement upgrade rate modifier
+ if (GC.getCivicInfo(eCivic).getImprovementUpgradeRateModifier() != 0)
+ {
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumImprovementInfos(); ++iI)
+ {
+ if (GC.getImprovementInfo((ImprovementTypes)iI).getImprovementUpgrade() != NO_IMPROVEMENT)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_CIVIC_IMPROVEMENT_UPGRADE", GC.getCivicInfo(eCivic).getImprovementUpgradeRateModifier()).c_str());
+ CvWString szImprovement;
+ szImprovement.Format(L"%s", GC.getImprovementInfo((ImprovementTypes)iI).getDescription());
+ setListHelp(szHelpText, szFirstBuffer, szImprovement, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+ }
+
+ // Military unit production modifier
+ if (GC.getCivicInfo(eCivic).getMilitaryProductionModifier() != 0)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_MILITARY_PRODUCTION", GC.getCivicInfo(eCivic).getMilitaryProductionModifier()));
+ }
+
+ // Free units population percent
+ if ((GC.getCivicInfo(eCivic).getBaseFreeUnits() != 0) || (GC.getCivicInfo(eCivic).getFreeUnitsPopulationPercent() != 0))
+ {
+ if (bPlayerContext)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_FREE_UNITS", (GC.getCivicInfo(eCivic).getBaseFreeUnits() + ((GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getTotalPopulation() * GC.getCivicInfo(eCivic).getFreeUnitsPopulationPercent()) / 100))));
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_UNIT_SUPPORT"));
+ }
+ }
+
+ // Free military units population percent
+ if ((GC.getCivicInfo(eCivic).getBaseFreeMilitaryUnits() != 0) || (GC.getCivicInfo(eCivic).getFreeMilitaryUnitsPopulationPercent() != 0))
+ {
+ if (bPlayerContext)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_FREE_MILITARY_UNITS", (GC.getCivicInfo(eCivic).getBaseFreeMilitaryUnits() + ((GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getTotalPopulation() * GC.getCivicInfo(eCivic).getFreeMilitaryUnitsPopulationPercent()) / 100))));
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_MILITARY_UNIT_SUPPORT"));
+ }
+ }
+
+ // Happiness per military unit
+ if (GC.getCivicInfo(eCivic).getHappyPerMilitaryUnit() != 0)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_UNIT_HAPPINESS", GC.getCivicInfo(eCivic).getHappyPerMilitaryUnit(), ((GC.getCivicInfo(eCivic).getHappyPerMilitaryUnit() > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR))));
+ }
+
+ // Military units produced with food
+ if (GC.getCivicInfo(eCivic).isMilitaryFoodProduction())
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_MILITARY_FOOD"));
+ }
+
+ // Conscription
+ if (getWorldSizeMaxConscript(eCivic) != 0)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_CONSCRIPTION", getWorldSizeMaxConscript(eCivic)));
+ }
+
+ // Population Unhealthiness
+ if (GC.getCivicInfo(eCivic).isNoUnhealthyPopulation())
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_NO_POP_UNHEALTHY"));
+ }
+
+ // Building Unhealthiness
+ if (GC.getCivicInfo(eCivic).isBuildingOnlyHealthy())
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_NO_BUILDING_UNHEALTHY"));
+ }
+
+ // Population Unhealthiness
+ if (0 != GC.getCivicInfo(eCivic).getExpInBorderModifier())
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_EXPERIENCE_IN_BORDERS", GC.getCivicInfo(eCivic).getExpInBorderModifier()));
+ }
+
+ // War Weariness
+ if (GC.getCivicInfo(eCivic).getWarWearinessModifier() != 0)
+ {
+ if (GC.getCivicInfo(eCivic).getWarWearinessModifier() <= -100)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_NO_WAR_WEARINESS"));
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_EXTRA_WAR_WEARINESS", GC.getCivicInfo(eCivic).getWarWearinessModifier()));
+ }
+ }
+
+ // Free specialists
+ if (GC.getCivicInfo(eCivic).getFreeSpecialist() != 0)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_FREE_SPECIALISTS", GC.getCivicInfo(eCivic).getFreeSpecialist()));
+ }
+
+ // Trade routes
+ if (GC.getCivicInfo(eCivic).getTradeRoutes() != 0)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_TRADE_ROUTES", GC.getCivicInfo(eCivic).getTradeRoutes()));
+ }
+
+ // No Foreign Trade
+ if (GC.getCivicInfo(eCivic).isNoForeignTrade())
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_NO_FOREIGN_TRADE"));
+ }
+
+ // No Corporations
+ if (GC.getCivicInfo(eCivic).isNoCorporations())
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_NO_CORPORATIONS"));
+ }
+
+ // No Foreign Corporations
+ if (GC.getCivicInfo(eCivic).isNoForeignCorporations())
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_NO_FOREIGN_CORPORATIONS"));
+ }
+
+ // Freedom Anger
+ if (GC.getCivicInfo(eCivic).getCivicPercentAnger() != 0)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_FREEDOM_ANGER", GC.getCivicInfo(eCivic).getTextKeyWide()));
+ }
+
+ if (!(GC.getCivicInfo(eCivic).isStateReligion()))
+ {
+ bFound = false;
+
+ for (iI = 0; iI < GC.getNumCivicInfos(); ++iI)
+ {
+ if ((GC.getCivicInfo((CivicTypes) iI).getCivicOptionType() == GC.getCivicInfo(eCivic).getCivicOptionType()) && (GC.getCivicInfo((CivicTypes) iI).isStateReligion()))
+ {
+ bFound = true;
+ }
+ }
+
+ if (bFound)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_NO_STATE_RELIGION"));
+ }
+ }
+
+ if (GC.getCivicInfo(eCivic).getStateReligionHappiness() != 0)
+ {
+ if (bPlayerContext && (GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getStateReligion() != NO_RELIGION))
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_STATE_RELIGION_HAPPINESS", abs(GC.getCivicInfo(eCivic).getStateReligionHappiness()), ((GC.getCivicInfo(eCivic).getStateReligionHappiness() > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR)), GC.getReligionInfo(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getStateReligion()).getChar()));
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_RELIGION_HAPPINESS", abs(GC.getCivicInfo(eCivic).getStateReligionHappiness()), ((GC.getCivicInfo(eCivic).getStateReligionHappiness() > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR))));
+ }
+ }
+
+ if (GC.getCivicInfo(eCivic).getNonStateReligionHappiness() != 0)
+ {
+ if (GC.getCivicInfo(eCivic).isStateReligion())
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_NON_STATE_REL_HAPPINESS_NO_STATE"));
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_NON_STATE_REL_HAPPINESS_WITH_STATE", abs(GC.getCivicInfo(eCivic).getNonStateReligionHappiness()), ((GC.getCivicInfo(eCivic).getNonStateReligionHappiness() > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR))));
+ }
+ }
+
+ // State Religion Unit Production Modifier
+ if (GC.getCivicInfo(eCivic).getStateReligionUnitProductionModifier() != 0)
+ {
+ if (bPlayerContext && (GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getStateReligion() != NO_RELIGION))
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_REL_TRAIN_BONUS", GC.getReligionInfo(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getStateReligion()).getChar(), GC.getCivicInfo(eCivic).getStateReligionUnitProductionModifier()));
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_STATE_REL_TRAIN_BONUS", GC.getCivicInfo(eCivic).getStateReligionUnitProductionModifier()));
+ }
+ }
+
+ // State Religion Building Production Modifier
+ if (GC.getCivicInfo(eCivic).getStateReligionBuildingProductionModifier() != 0)
+ {
+ if (bPlayerContext && (GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getStateReligion() != NO_RELIGION))
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_REL_BUILDING_BONUS", GC.getReligionInfo(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getStateReligion()).getChar(), GC.getCivicInfo(eCivic).getStateReligionBuildingProductionModifier()));
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_STATE_REL_BUILDING_BONUS", GC.getCivicInfo(eCivic).getStateReligionBuildingProductionModifier()));
+ }
+ }
+
+ // State Religion Free Experience
+ if (GC.getCivicInfo(eCivic).getStateReligionFreeExperience() != 0)
+ {
+ if (bPlayerContext && (GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getStateReligion() != NO_RELIGION))
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_REL_FREE_XP", GC.getCivicInfo(eCivic).getStateReligionFreeExperience(), GC.getReligionInfo(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getStateReligion()).getChar()));
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_STATE_REL_FREE_XP", GC.getCivicInfo(eCivic).getStateReligionFreeExperience()));
+ }
+ }
+
+ if (GC.getCivicInfo(eCivic).isNoNonStateReligionSpread())
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_NO_NON_STATE_SPREAD"));
+ }
+
+ // Yield Modifiers
+ setYieldChangeHelp(szHelpText, L"", L"", gDLL->getText("TXT_KEY_CIVIC_IN_ALL_CITIES").GetCString(), GC.getCivicInfo(eCivic).getYieldModifierArray(), true);
+
+ // Capital Yield Modifiers
+ setYieldChangeHelp(szHelpText, L"", L"", gDLL->getText("TXT_KEY_CIVIC_IN_CAPITAL").GetCString(), GC.getCivicInfo(eCivic).getCapitalYieldModifierArray(), true);
+
+ // Trade Yield Modifiers
+ setYieldChangeHelp(szHelpText, L"", L"", gDLL->getText("TXT_KEY_CIVIC_FROM_TRADE_ROUTES").GetCString(), GC.getCivicInfo(eCivic).getTradeYieldModifierArray(), true);
+
+ // Commerce Modifier
+ setCommerceChangeHelp(szHelpText, L"", L"", gDLL->getText("TXT_KEY_CIVIC_IN_ALL_CITIES").GetCString(), GC.getCivicInfo(eCivic).getCommerceModifierArray(), true);
+
+ // Capital Commerce Modifiers
+ setCommerceChangeHelp(szHelpText, L"", L"", gDLL->getText("TXT_KEY_CIVIC_IN_CAPITAL").GetCString(), GC.getCivicInfo(eCivic).getCapitalCommerceModifierArray(), true);
+
+ // Specialist Commerce
+ setCommerceChangeHelp(szHelpText, L"", L"", gDLL->getText("TXT_KEY_CIVIC_PER_SPECIALIST").GetCString(), GC.getCivicInfo(eCivic).getSpecialistExtraCommerceArray());
+
+ // Largest City Happiness
+ if (GC.getCivicInfo(eCivic).getLargestCityHappiness() != 0)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_LARGEST_CITIES_HAPPINESS", GC.getCivicInfo(eCivic).getLargestCityHappiness(), ((GC.getCivicInfo(eCivic).getLargestCityHappiness() > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR)), GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getTargetNumCities()));
+ }
+
+ // Improvement Yields
+ for (iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ iLast = 0;
+
+ for (iJ = 0; iJ < GC.getNumImprovementInfos(); iJ++)
+ {
+ if (GC.getCivicInfo(eCivic).getImprovementYieldChanges(iJ, iI) != 0)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_CIVIC_IMPROVEMENT_YIELD_CHANGE", GC.getCivicInfo(eCivic).getImprovementYieldChanges(iJ, iI), GC.getYieldInfo((YieldTypes)iI).getChar()).c_str());
+ CvWString szImprovement;
+ szImprovement.Format(L"%s", GC.getImprovementInfo((ImprovementTypes)iJ).getDescription());
+ setListHelp(szHelpText, szFirstBuffer, szImprovement, L", ", (GC.getCivicInfo(eCivic).getImprovementYieldChanges(iJ, iI) != iLast));
+ iLast = GC.getCivicInfo(eCivic).getImprovementYieldChanges(iJ, iI);
+ }
+ }
+ }
+
+ // Building Yields Changes, AGDM addition
+ for (iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ iLast = 0;
+
+ for (iJ = 0; iJ < GC.getNumBuildingClassInfos(); iJ++)
+ {
+ if (GC.getCivicInfo(eCivic).getBuildingYieldChanges(iJ, iI) != 0)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_CIVIC_BUILDING_YIELD_CHANGE", GC.getCivicInfo(eCivic).getBuildingYieldChanges(iJ, iI), GC.getYieldInfo((YieldTypes)iI).getChar()).c_str());
+ CvWString szBuilding;
+ if (bPlayerContext && NO_PLAYER != GC.getGameINLINE().getActivePlayer())
+ {
+ BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(GC.getGameINLINE().getActiveCivilizationType()).getCivilizationBuildings(iJ);
+ if (NO_BUILDING != eBuilding)
+ {
+ szBuilding.Format(L"%s", GC.getBuildingInfo(eBuilding).getDescription());
+ }
+ }
+ else
+ {
+ szBuilding.Format(L"%s", GC.getBuildingClassInfo((BuildingClassTypes)iJ).getDescription());
+ }
+ setListHelp(szHelpText, szFirstBuffer, szBuilding, L", ", (GC.getCivicInfo(eCivic).getBuildingYieldChanges(iJ, iI) != iLast));
+ iLast = GC.getCivicInfo(eCivic).getBuildingYieldChanges(iJ, iI);
+ }
+ }
+ }
+
+ // Building Yields Modifiers, AGDM addition
+ for (iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ iLast = 0;
+
+ for (iJ = 0; iJ < GC.getNumBuildingClassInfos(); iJ++)
+ {
+ if (GC.getCivicInfo(eCivic).getBuildingYieldModifiers(iJ, iI) != 0)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_CIVIC_BUILDING_YIELD_MODIFIER", GC.getCivicInfo(eCivic).getBuildingYieldModifiers(iJ, iI), GC.getYieldInfo((YieldTypes)iI).getChar()).c_str());
+ CvWString szBuilding;
+ if (bPlayerContext && NO_PLAYER != GC.getGameINLINE().getActivePlayer())
+ {
+ BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(GC.getGameINLINE().getActiveCivilizationType()).getCivilizationBuildings(iJ);
+ if (NO_BUILDING != eBuilding)
+ {
+ szBuilding.Format(L"%s", GC.getBuildingInfo(eBuilding).getDescription());
+ }
+ }
+ else
+ {
+ szBuilding.Format(L"%s", GC.getBuildingClassInfo((BuildingClassTypes)iJ).getDescription());
+ }
+ setListHelp(szHelpText, szFirstBuffer, szBuilding, L", ", (GC.getCivicInfo(eCivic).getBuildingYieldModifiers(iJ, iI) != iLast));
+ iLast = GC.getCivicInfo(eCivic).getBuildingYieldModifiers(iJ, iI);
+ }
+ }
+ }
+
+ // Building Commerce Changes, AGDM addition
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; ++iI)
+ {
+ iLast = 0;
+
+ for (iJ = 0; iJ < GC.getNumBuildingClassInfos(); iJ++)
+ {
+ if (GC.getCivicInfo(eCivic).getBuildingCommerceChanges(iJ, iI) != 0)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_CIVIC_BUILDING_COMMERCE_CHANGE", GC.getCivicInfo(eCivic).getBuildingCommerceChanges(iJ, iI), GC.getCommerceInfo((CommerceTypes) iI).getChar()).c_str());
+ CvWString szBuilding;
+ if (bPlayerContext && NO_PLAYER != GC.getGameINLINE().getActivePlayer())
+ {
+ BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(GC.getGameINLINE().getActiveCivilizationType()).getCivilizationBuildings(iJ);
+ if (NO_BUILDING != eBuilding)
+ {
+ szBuilding.Format(L"%s", GC.getBuildingInfo(eBuilding).getDescription());
+ }
+ }
+ else
+ {
+ szBuilding.Format(L"%s", GC.getBuildingClassInfo((BuildingClassTypes)iJ).getDescription());
+ }
+ setListHelp(szHelpText, szFirstBuffer, szBuilding, L", ", (GC.getCivicInfo(eCivic).getBuildingCommerceChanges(iJ, iI) != iLast));
+ iLast = GC.getCivicInfo(eCivic).getBuildingCommerceChanges(iJ, iI);
+ }
+ }
+ }
+
+ // Building Commerce Modifiers, AGDM addition
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; ++iI)
+ {
+ iLast = 0;
+
+ for (iJ = 0; iJ < GC.getNumBuildingClassInfos(); iJ++)
+ {
+ if (GC.getCivicInfo(eCivic).getBuildingCommerceModifiers(iJ, iI) != 0)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_CIVIC_BUILDING_COMMERCE_MODIFIER", GC.getCivicInfo(eCivic).getBuildingCommerceModifiers(iJ, iI), GC.getCommerceInfo((CommerceTypes) iI).getChar()).c_str());
+ CvWString szBuilding;
+ if (bPlayerContext && NO_PLAYER != GC.getGameINLINE().getActivePlayer())
+ {
+ BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(GC.getGameINLINE().getActiveCivilizationType()).getCivilizationBuildings(iJ);
+ if (NO_BUILDING != eBuilding)
+ {
+ szBuilding.Format(L"%s", GC.getBuildingInfo(eBuilding).getDescription());
+ }
+ }
+ else
+ {
+ szBuilding.Format(L"%s", GC.getBuildingClassInfo((BuildingClassTypes)iJ).getDescription());
+ }
+ setListHelp(szHelpText, szFirstBuffer, szBuilding, L", ", (GC.getCivicInfo(eCivic).getBuildingCommerceModifiers(iJ, iI) != iLast));
+ iLast = GC.getCivicInfo(eCivic).getBuildingCommerceModifiers(iJ, iI);
+ }
+ }
+ }
+
+ // Building giving Free Specialists, AGDM addition
+ for (iI = 0; iI < GC.getNumSpecialistInfos(); ++iI)
+ {
+ iLast = 0;
+
+ for (iJ = 0; iJ < GC.getNumBuildingClassInfos(); iJ++)
+ {
+ if (GC.getCivicInfo(eCivic).getBuildingFreeSpecialistCounts(iJ, iI) != 0)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_CIVIC_BUILDING_FREE_SPECIALIST", GC.getCivicInfo(eCivic).getBuildingFreeSpecialistCounts(iJ, iI), GC.getSpecialistInfo((SpecialistTypes)iI).getTextKeyWide()).c_str());
+ CvWString szBuilding;
+ if (bPlayerContext && NO_PLAYER != GC.getGameINLINE().getActivePlayer())
+ {
+ BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(GC.getGameINLINE().getActiveCivilizationType()).getCivilizationBuildings(iJ);
+ if (NO_BUILDING != eBuilding)
+ {
+ szBuilding.Format(L"%s", GC.getBuildingInfo(eBuilding).getDescription());
+ }
+ }
+ else
+ {
+ szBuilding.Format(L"%s", GC.getBuildingClassInfo((BuildingClassTypes)iJ).getDescription());
+ }
+ setListHelp(szHelpText, szFirstBuffer, szBuilding, L", ", (GC.getCivicInfo(eCivic).getBuildingFreeSpecialistCounts(iJ, iI) != iLast));
+ iLast = GC.getCivicInfo(eCivic).getBuildingFreeSpecialistCounts(iJ, iI);
+ }
+ }
+ }
+
+ // Building Happiness
+ for (iI = 0; iI < GC.getNumBuildingClassInfos(); ++iI)
+ {
+ if (GC.getCivicInfo(eCivic).getBuildingHappinessChanges(iI) != 0)
+ {
+ if (bPlayerContext && NO_PLAYER != GC.getGameINLINE().getActivePlayer())
+ {
+ BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(GC.getGameINLINE().getActiveCivilizationType()).getCivilizationBuildings(iI);
+ if (NO_BUILDING != eBuilding)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_BUILDING_HAPPINESS", GC.getCivicInfo(eCivic).getBuildingHappinessChanges(iI), ((GC.getCivicInfo(eCivic).getBuildingHappinessChanges(iI) > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR)), GC.getBuildingInfo(eBuilding).getTextKeyWide()));
+ }
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_BUILDING_HAPPINESS", GC.getCivicInfo(eCivic).getBuildingHappinessChanges(iI), ((GC.getCivicInfo(eCivic).getBuildingHappinessChanges(iI) > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR)), GC.getBuildingClassInfo((BuildingClassTypes)iI).getTextKeyWide()));
+ }
+ }
+
+ if (GC.getCivicInfo(eCivic).getBuildingHealthChanges(iI) != 0)
+ {
+ if (bPlayerContext && NO_PLAYER != GC.getGameINLINE().getActivePlayer())
+ {
+ BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(GC.getGameINLINE().getActiveCivilizationType()).getCivilizationBuildings(iI);
+ if (NO_BUILDING != eBuilding)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_BUILDING_HAPPINESS", GC.getCivicInfo(eCivic).getBuildingHealthChanges(iI), ((GC.getCivicInfo(eCivic).getBuildingHealthChanges(iI) > 0) ? gDLL->getSymbolID(HEALTHY_CHAR) : gDLL->getSymbolID(UNHEALTHY_CHAR)), GC.getBuildingInfo(eBuilding).getTextKeyWide()));
+ }
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_BUILDING_HAPPINESS", GC.getCivicInfo(eCivic).getBuildingHealthChanges(iI), ((GC.getCivicInfo(eCivic).getBuildingHealthChanges(iI) > 0) ? gDLL->getSymbolID(HEALTHY_CHAR) : gDLL->getSymbolID(UNHEALTHY_CHAR)), GC.getBuildingClassInfo((BuildingClassTypes)iI).getTextKeyWide()));
+ }
+ }
+
+ // Building free experience, AGDM addition
+ if (GC.getCivicInfo(eCivic).getBuildingFreeExperiences(iI) != 0)
+ {
+ if (bPlayerContext && NO_PLAYER != GC.getGameINLINE().getActivePlayer())
+ {
+ BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(GC.getGameINLINE().getActiveCivilizationType()).getCivilizationBuildings(iI);
+ if (NO_BUILDING != eBuilding)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_BUILDING_FREE_EXPERIENCE", GC.getCivicInfo(eCivic).getBuildingFreeExperiences(iI), GC.getBuildingInfo(eBuilding).getTextKeyWide()));
+ }
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_BUILDING_FREE_EXPERIENCE", GC.getCivicInfo(eCivic).getBuildingFreeExperiences(iI), GC.getBuildingClassInfo((BuildingClassTypes)iI).getTextKeyWide()));
+ }
+ }
+
+ // Building military production bonus, AGDM addition
+ if (GC.getCivicInfo(eCivic).getBuildingMilitaryProductionModifiers(iI) != 0)
+ {
+ if (bPlayerContext && NO_PLAYER != GC.getGameINLINE().getActivePlayer())
+ {
+ BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(GC.getGameINLINE().getActiveCivilizationType()).getCivilizationBuildings(iI);
+ if (NO_BUILDING != eBuilding)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_BUILDING_MILITARY_PRODUCTION", GC.getCivicInfo(eCivic).getBuildingMilitaryProductionModifiers(iI), GC.getBuildingInfo(eBuilding).getTextKeyWide()));
+ }
+ }
+ else
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_BUILDING_MILITARY_PRODUCTION", GC.getCivicInfo(eCivic).getBuildingMilitaryProductionModifiers(iI), GC.getBuildingClassInfo((BuildingClassTypes)iI).getTextKeyWide()));
+ }
+ }
+ }
+
+ // Feature Happiness
+ iLast = 0;
+
+ for (iI = 0; iI < GC.getNumFeatureInfos(); ++iI)
+ {
+ if (GC.getCivicInfo(eCivic).getFeatureHappinessChanges(iI) != 0)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_CIVIC_FEATURE_HAPPINESS", GC.getCivicInfo(eCivic).getFeatureHappinessChanges(iI), ((GC.getCivicInfo(eCivic).getFeatureHappinessChanges(iI) > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR))).c_str());
+ CvWString szFeature;
+ szFeature.Format(L"%s", GC.getFeatureInfo((FeatureTypes)iI).getDescription());
+ setListHelp(szHelpText, szFirstBuffer, szFeature, L", ", (GC.getCivicInfo(eCivic).getFeatureHappinessChanges(iI) != iLast));
+ iLast = GC.getCivicInfo(eCivic).getFeatureHappinessChanges(iI);
+ }
+ }
+
+ // Hurry types
+ for (iI = 0; iI < GC.getNumHurryInfos(); ++iI)
+ {
+ if (GC.getCivicInfo(eCivic).isHurry(iI))
+ {
+ szHelpText.append(CvWString::format(L"%s%c%s", NEWLINE, gDLL->getSymbolID(BULLET_CHAR), GC.getHurryInfo((HurryTypes)iI).getDescription()));
+ }
+ }
+
+ // Gold cost per unit
+ if (GC.getCivicInfo(eCivic).getGoldPerUnit() != 0)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_SUPPORT_COSTS", (GC.getCivicInfo(eCivic).getGoldPerUnit() > 0), GC.getCommerceInfo(COMMERCE_GOLD).getChar()));
+ }
+
+ // Gold cost per military unit
+ if (GC.getCivicInfo(eCivic).getGoldPerMilitaryUnit() != 0)
+ {
+ szHelpText.append(NEWLINE);
+ szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_MILITARY_SUPPORT_COSTS", (GC.getCivicInfo(eCivic).getGoldPerMilitaryUnit() > 0), GC.getCommerceInfo(COMMERCE_GOLD).getChar()));
+ }
+
+ if (!CvWString(GC.getCivicInfo(eCivic).getHelp()).empty())
+ {
+ szHelpText.append(CvWString::format(L"%s%s", NEWLINE, GC.getCivicInfo(eCivic).getHelp()).c_str());
+ }
+}
+
+
+void CvGameTextMgr::setTechHelp(CvWStringBuffer &szBuffer, TechTypes eTech, bool bCivilopediaText, bool bPlayerContext, bool bStrategyText, bool bTreeInfo, TechTypes eFromTech)
+{
+ PROFILE_FUNC();
+
+ CvWString szTempBuffer;
+ CvWString szFirstBuffer;
+ BuildingTypes eLoopBuilding;
+ UnitTypes eLoopUnit;
+ bool bFirst;
+ int iI;
+
+ // show debug info if cheat level > 0 and alt down
+ bool bAlt = gDLL->altKey();
+ if (bAlt && (gDLL->getChtLvl() > 0))
+ {
+ szBuffer.clear();
+
+ for (int iI = 0; iI < MAX_PLAYERS; ++iI)
+ {
+ CvPlayerAI* playerI = &GET_PLAYER((PlayerTypes)iI);
+ CvTeamAI* teamI = &GET_TEAM(playerI->getTeam());
+ if (playerI->isAlive())
+ {
+ szTempBuffer.Format(L"%s: ", playerI->getName());
+ szBuffer.append(szTempBuffer);
+
+ TechTypes ePlayerTech = playerI->getCurrentResearch();
+ if (ePlayerTech == NO_TECH)
+ szTempBuffer.Format(L"-\n");
+ else
+ szTempBuffer.Format(L"%s (%d->%dt)(%d/%d)\n", GC.getTechInfo(ePlayerTech).getDescription(), playerI->calculateResearchRate(ePlayerTech), playerI->getResearchTurnsLeft(ePlayerTech, true), teamI->getResearchProgress(ePlayerTech), teamI->getResearchCost(ePlayerTech));
+
+ szBuffer.append(szTempBuffer);
+ }
+ }
+
+ return;
+ }
+
+
+ if (NO_TECH == eTech)
+ {
+ return;
+ }
+
+ // Tech Name
+ if (!bCivilopediaText && (!bTreeInfo || (NO_TECH == eFromTech)))
+ {
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_TECH_TEXT"), GC.getTechInfo(eTech).getDescription());
+ szBuffer.append(szTempBuffer);
+ }
+
+ FAssert(GC.getGameINLINE().getActivePlayer() != NO_PLAYER || !bPlayerContext);
+
+ if (bTreeInfo && (NO_TECH != eFromTech))
+ {
+ buildTechTreeString(szBuffer, eTech, bPlayerContext, eFromTech);
+ }
+
+ // Obsolete Buildings
+ for (iI = 0; iI < GC.getNumBuildingClassInfos(); ++iI)
+ {
+ if (!bPlayerContext || (GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getBuildingClassCount((BuildingClassTypes)iI) > 0))
+ {
+ if (GC.getGameINLINE().getActivePlayer() != NO_PLAYER)
+ {
+ eLoopBuilding = (BuildingTypes)GC.getCivilizationInfo(GC.getGameINLINE().getActiveCivilizationType()).getCivilizationBuildings(iI);
+ }
+ else
+ {
+ eLoopBuilding = (BuildingTypes)GC.getBuildingClassInfo((BuildingClassTypes)iI).getDefaultBuildingIndex();
+ }
+
+ if (eLoopBuilding != NO_BUILDING)
+ {
+ // Obsolete Buildings Check...
+ if (GC.getBuildingInfo(eLoopBuilding).getObsoleteTech() == eTech)
+ {
+ buildObsoleteString(szBuffer, eLoopBuilding, true);
+ }
+ }
+ }
+ }
+
+ // Obsolete Bonuses
+ for (iI = 0; iI < GC.getNumBonusInfos(); ++iI)
+ {
+ if (GC.getBonusInfo((BonusTypes)iI).getTechObsolete() == eTech)
+ {
+ buildObsoleteBonusString(szBuffer, iI, true);
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumSpecialBuildingInfos(); ++iI)
+ {
+ if (GC.getSpecialBuildingInfo((SpecialBuildingTypes) iI).getObsoleteTech() == eTech)
+ {
+ buildObsoleteSpecialString(szBuffer, iI, true);
+ }
+ }
+
+ // Route movement change...
+ buildMoveString(szBuffer, eTech, true, bPlayerContext);
+
+ // Creates a free unit...
+ buildFreeUnitString(szBuffer, eTech, true, bPlayerContext);
+
+ // Increases feature production...
+ buildFeatureProductionString(szBuffer, eTech, true, bPlayerContext);
+
+ // Increases worker build rate...
+ buildWorkerRateString(szBuffer, eTech, true, bPlayerContext);
+
+ // Trade Routed per city change...
+ buildTradeRouteString(szBuffer, eTech, true, bPlayerContext);
+
+ // Health increase...
+ buildHealthRateString(szBuffer, eTech, true, bPlayerContext);
+
+ // Happiness increase...
+ buildHappinessRateString(szBuffer, eTech, true, bPlayerContext);
+
+ // Free Techs...
+ buildFreeTechString(szBuffer, eTech, true, bPlayerContext);
+
+ // Line of Sight Bonus across water...
+ buildLOSString(szBuffer, eTech, true, bPlayerContext);
+
+ // Centers world map...
+ buildMapCenterString(szBuffer, eTech, true, bPlayerContext);
+
+ // Reveals World Map...
+ buildMapRevealString(szBuffer, eTech, true);
+
+ // Enables map trading...
+ buildMapTradeString(szBuffer, eTech, true, bPlayerContext);
+
+ // Enables tech trading...
+ buildTechTradeString(szBuffer, eTech, true, bPlayerContext);
+
+ // Enables gold trading...
+ buildGoldTradeString(szBuffer, eTech, true, bPlayerContext);
+
+ // Enables open borders...
+ buildOpenBordersString(szBuffer, eTech, true, bPlayerContext);
+
+ // Enables defensive pacts...
+ buildDefensivePactString(szBuffer, eTech, true, bPlayerContext);
+
+ // Enables permanent alliances...
+ buildPermanentAllianceString(szBuffer, eTech, true, bPlayerContext);
+
+ // Enables bridge building...
+ buildBridgeString(szBuffer, eTech, true, bPlayerContext);
+
+ // Can spread irrigation...
+ buildIrrigationString(szBuffer, eTech, true, bPlayerContext);
+
+ // Ignore irrigation...
+ buildIgnoreIrrigationString(szBuffer, eTech, true, bPlayerContext);
+
+ // Coastal work...
+ buildWaterWorkString(szBuffer, eTech, true, bPlayerContext);
+
+ // Enables permanent alliances...
+ buildVassalStateString(szBuffer, eTech, true, bPlayerContext);
+
+ // Build farm, irrigation, etc...
+ for (iI = 0; iI < GC.getNumBuildInfos(); ++iI)
+ {
+ buildImprovementString(szBuffer, eTech, iI, true, bPlayerContext);
+ }
+
+ // Extra moves for certain domains...
+ for (iI = 0; iI < NUM_DOMAIN_TYPES; ++iI)
+ {
+ buildDomainExtraMovesString(szBuffer, eTech, iI, true, bPlayerContext);
+ }
+
+ // Adjusting culture, science, etc
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; ++iI)
+ {
+ buildAdjustString(szBuffer, eTech, iI, true, bPlayerContext);
+ }
+
+ // Enabling trade routes on water...?
+ for (iI = 0; iI < GC.getNumTerrainInfos(); ++iI)
+ {
+ buildTerrainTradeString(szBuffer, eTech, iI, true, bPlayerContext);
+ }
+
+ buildRiverTradeString(szBuffer, eTech, true, bPlayerContext);
+
+ // Special Buildings
+ for (iI = 0; iI < GC.getNumSpecialBuildingInfos(); ++iI)
+ {
+ buildSpecialBuildingString(szBuffer, eTech, iI, true, bPlayerContext);
+ }
+
+ // Build farm, mine, etc...
+ for (iI = 0; iI < GC.getNumImprovementInfos(); ++iI)
+ {
+ buildYieldChangeString(szBuffer, eTech, iI, true, bPlayerContext);
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumBonusInfos(); ++iI)
+ {
+ bFirst = buildBonusRevealString(szBuffer, eTech, iI, bFirst, true, bPlayerContext);
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumCivicInfos(); ++iI)
+ {
+ bFirst = buildCivicRevealString(szBuffer, eTech, iI, bFirst, true, bPlayerContext);
+ }
+
+ if (!bCivilopediaText)
+ {
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); ++iI)
+ {
+ if (!bPlayerContext || !(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).isProductionMaxedUnitClass((UnitClassTypes)iI)))
+ {
+ if (GC.getGameINLINE().getActivePlayer() != NO_PLAYER)
+ {
+ eLoopUnit = (UnitTypes)GC.getCivilizationInfo(GC.getGameINLINE().getActiveCivilizationType()).getCivilizationUnits(iI);
+ }
+ else
+ {
+ eLoopUnit = (UnitTypes)GC.getUnitClassInfo((UnitClassTypes)iI).getDefaultUnitIndex();
+ }
+
+ if (eLoopUnit != NO_UNIT)
+ {
+ if (!bPlayerContext || !(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).canTrain(eLoopUnit)))
+ {
+ if (GC.getUnitInfo(eLoopUnit).getPrereqAndTech() == eTech)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_TECH_CAN_TRAIN").c_str());
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_UNIT_TEXT"), GC.getUnitInfo(eLoopUnit).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ else
+ {
+ for (int iJ = 0; iJ < GC.getNUM_UNIT_AND_TECH_PREREQS(); iJ++)
+ {
+ if (GC.getUnitInfo(eLoopUnit).getPrereqAndTechs(iJ) == eTech)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_TECH_CAN_TRAIN").c_str());
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_UNIT_TEXT"), GC.getUnitInfo(eLoopUnit).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumBuildingClassInfos(); ++iI)
+ {
+ if (!bPlayerContext || !(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).isProductionMaxedBuildingClass((BuildingClassTypes)iI)))
+ {
+ if (GC.getGameINLINE().getActivePlayer() != NO_PLAYER)
+ {
+ eLoopBuilding = (BuildingTypes)GC.getCivilizationInfo(GC.getGameINLINE().getActiveCivilizationType()).getCivilizationBuildings(iI);
+ }
+ else
+ {
+ eLoopBuilding = (BuildingTypes)GC.getBuildingClassInfo((BuildingClassTypes)iI).getDefaultBuildingIndex();
+ }
+
+ if (eLoopBuilding != NO_BUILDING)
+ {
+ if (!bPlayerContext || !(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).canConstruct(eLoopBuilding, false, true)))
+ {
+ if (GC.getBuildingInfo(eLoopBuilding).getPrereqAndTech() == eTech)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_TECH_CAN_CONSTRUCT").c_str());
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_BUILDING_TEXT"), GC.getBuildingInfo(eLoopBuilding).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ else
+ {
+ for (int iJ = 0; iJ < GC.getNUM_BUILDING_AND_TECH_PREREQS(); iJ++)
+ {
+ if (GC.getBuildingInfo(eLoopBuilding).getPrereqAndTechs(iJ) == eTech)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_TECH_CAN_CONSTRUCT").c_str());
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_BUILDING_TEXT"), GC.getBuildingInfo(eLoopBuilding).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumProjectInfos(); ++iI)
+ {
+ if (!bPlayerContext || !(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).isProductionMaxedProject((ProjectTypes)iI)))
+ {
+ if (!bPlayerContext || !(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).canCreate(((ProjectTypes)iI), false, true)))
+ {
+ if (GC.getProjectInfo((ProjectTypes)iI).getTechPrereq() == eTech)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_TECH_CAN_CREATE").c_str());
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_PROJECT_TEXT"), GC.getProjectInfo((ProjectTypes)iI).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+ }
+ }
+ }
+
+ bFirst = true;
+ for (iI = 0; iI < GC.getNumProcessInfos(); ++iI)
+ {
+ bFirst = buildProcessInfoString(szBuffer, eTech, iI, bFirst, true, bPlayerContext);
+ }
+
+ bFirst = true;
+ for (iI = 0; iI < GC.getNumReligionInfos(); ++iI)
+ {
+ if (!bPlayerContext || !(GC.getGameINLINE().isReligionSlotTaken((ReligionTypes)iI)))
+ {
+ bFirst = buildFoundReligionString(szBuffer, eTech, iI, bFirst, true, bPlayerContext);
+ }
+ }
+
+ bFirst = true;
+ for (iI = 0; iI < GC.getNumCorporationInfos(); ++iI)
+ {
+ if (!bPlayerContext || !(GC.getGameINLINE().isCorporationFounded((CorporationTypes)iI)))
+ {
+ bFirst = buildFoundCorporationString(szBuffer, eTech, iI, bFirst, true, bPlayerContext);
+ }
+ }
+
+ bFirst = true;
+ for (iI = 0; iI < GC.getNumPromotionInfos(); ++iI)
+ {
+ bFirst = buildPromotionString(szBuffer, eTech, iI, bFirst, true, bPlayerContext);
+ }
+
+ if (bTreeInfo && NO_TECH == eFromTech)
+ {
+ buildSingleLineTechTreeString(szBuffer, eTech, bPlayerContext);
+ }
+
+ if (!CvWString(GC.getTechInfo(eTech).getHelp()).empty())
+ {
+ szBuffer.append(CvWString::format(L"%s%s", NEWLINE, GC.getTechInfo(eTech).getHelp()).c_str());
+ }
+
+ if (!bCivilopediaText)
+ {
+ if (GC.getGameINLINE().getActivePlayer() == NO_PLAYER)
+ {
+ szTempBuffer.Format(L"\n%d%c", GC.getTechInfo(eTech).getResearchCost(), GC.getCommerceInfo(COMMERCE_RESEARCH).getChar());
+ szBuffer.append(szTempBuffer);
+ }
+ else if (GET_TEAM(GC.getGameINLINE().getActiveTeam()).isHasTech(eTech))
+ {
+ szTempBuffer.Format(L"\n%d%c", GET_TEAM(GC.getGameINLINE().getActiveTeam()).getResearchCost(eTech), GC.getCommerceInfo(COMMERCE_RESEARCH).getChar());
+ szBuffer.append(szTempBuffer);
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_TECH_NUM_TURNS", GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getResearchTurnsLeft(eTech, (gDLL->ctrlKey() || !(gDLL->shiftKey())))));
+
+ szTempBuffer.Format(L" (%d/%d %c)", GET_TEAM(GC.getGameINLINE().getActiveTeam()).getResearchProgress(eTech), GET_TEAM(GC.getGameINLINE().getActiveTeam()).getResearchCost(eTech), GC.getCommerceInfo(COMMERCE_RESEARCH).getChar());
+ szBuffer.append(szTempBuffer);
+ }
+ }
+
+ if (GC.getGameINLINE().getActivePlayer() != NO_PLAYER)
+ {
+ if (GET_PLAYER(GC.getGameINLINE().getActivePlayer()).canResearch(eTech))
+ {
+ for (iI = 0; iI < GC.getNumUnitInfos(); ++iI)
+ {
+ CvUnitInfo& kUnit = GC.getUnitInfo((UnitTypes)iI);
+
+ if (kUnit.getBaseDiscover() > 0 || kUnit.getDiscoverMultiplier() > 0)
+ {
+ if (::getDiscoveryTech((UnitTypes)iI, GC.getGameINLINE().getActivePlayer()) == eTech)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_TECH_GREAT_PERSON_DISCOVER", kUnit.getTextKeyWide()));
+ }
+ }
+ }
+
+ if (GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getCurrentEra() < GC.getTechInfo(eTech).getEra())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_TECH_ERA_ADVANCE", GC.getEraInfo((EraTypes)GC.getTechInfo(eTech).getEra()).getTextKeyWide()));
+ }
+ }
+ }
+
+ if (bStrategyText)
+ {
+ if (!CvWString(GC.getTechInfo(eTech).getStrategy()).empty())
+ {
+ if ((GC.getGameINLINE().getActivePlayer() == NO_PLAYER) || GET_PLAYER(GC.getGameINLINE().getActivePlayer()).isOption(PLAYEROPTION_ADVISOR_HELP))
+ {
+ szBuffer.append(SEPARATOR);
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_SIDS_TIPS"));
+ szBuffer.append(L'\"');
+ szBuffer.append(GC.getTechInfo(eTech).getStrategy());
+ szBuffer.append(L'\"');
+ }
+ }
+ }
+}
+
+
+void CvGameTextMgr::setBasicUnitHelp(CvWStringBuffer &szBuffer, UnitTypes eUnit, bool bCivilopediaText)
+{
+ PROFILE_FUNC();
+
+ CvWString szTempBuffer;
+ bool bFirst;
+ int iCount;
+ int iI;
+
+ if (NO_UNIT == eUnit)
+ {
+ return;
+ }
+
+ if (!bCivilopediaText)
+ {
+ szBuffer.append(NEWLINE);
+
+ if (GC.getUnitInfo(eUnit).getDomainType() == DOMAIN_AIR)
+ {
+ if (GC.getUnitInfo(eUnit).getAirCombat() > 0)
+ {
+ szTempBuffer.Format(L"%d%c, ", GC.getUnitInfo(eUnit).getAirCombat(), gDLL->getSymbolID(STRENGTH_CHAR));
+ szBuffer.append(szTempBuffer);
+ }
+ }
+ else
+ {
+ if (GC.getUnitInfo(eUnit).getCombat() > 0)
+ {
+ szTempBuffer.Format(L"%d%c, ", GC.getUnitInfo(eUnit).getCombat(), gDLL->getSymbolID(STRENGTH_CHAR));
+ szBuffer.append(szTempBuffer);
+ }
+ }
+
+ szTempBuffer.Format(L"%d%c", GC.getUnitInfo(eUnit).getMoves(), gDLL->getSymbolID(MOVES_CHAR));
+ szBuffer.append(szTempBuffer);
+
+ if (GC.getUnitInfo(eUnit).getAirRange() > 0)
+ {
+ szBuffer.append(L", ");
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_AIR_RANGE", GC.getUnitInfo(eUnit).getAirRange()));
+ }
+ }
+
+ if (GC.getUnitInfo(eUnit).isGoldenAge())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_GOLDEN_AGE"));
+ }
+
+ if (GC.getUnitInfo(eUnit).getLeaderExperience() > 0)
+ {
+ if (0 == GC.getDefineINT("WARLORD_EXTRA_EXPERIENCE_PER_UNIT_PERCENT"))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_LEADER", GC.getUnitInfo(eUnit).getLeaderExperience()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_LEADER_EXPERIENCE", GC.getUnitInfo(eUnit).getLeaderExperience()));
+ }
+ }
+
+ if (NO_PROMOTION != GC.getUnitInfo(eUnit).getLeaderPromotion())
+ {
+ szBuffer.append(CvWString::format(L"%s%c%s", NEWLINE, gDLL->getSymbolID(BULLET_CHAR), gDLL->getText("TXT_KEY_PROMOTION_WHEN_LEADING").GetCString()));
+ parsePromotionHelp(szBuffer, (PromotionTypes)GC.getUnitInfo(eUnit).getLeaderPromotion(), L"\n ");
+ }
+
+ if ((GC.getUnitInfo(eUnit).getBaseDiscover() > 0) || (GC.getUnitInfo(eUnit).getDiscoverMultiplier() > 0))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_DISCOVER_TECH"));
+ }
+
+ if ((GC.getUnitInfo(eUnit).getBaseHurry() > 0) || (GC.getUnitInfo(eUnit).getHurryMultiplier() > 0))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_HURRY_PRODUCTION"));
+ }
+
+ if ((GC.getUnitInfo(eUnit).getBaseTrade() > 0) || (GC.getUnitInfo(eUnit).getTradeMultiplier() > 0))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_TRADE_MISSION"));
+ }
+
+ if (GC.getUnitInfo(eUnit).getGreatWorkCulture() > 0)
+ {
+ int iCulture = GC.getUnitInfo(eUnit).getGreatWorkCulture();
+ if (NO_GAMESPEED != GC.getGameINLINE().getGameSpeedType())
+ {
+ iCulture *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getUnitGreatWorkPercent();
+ iCulture /= 100;
+ }
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_GREAT_WORK", iCulture));
+ }
+
+ if (GC.getUnitInfo(eUnit).getEspionagePoints() > 0)
+ {
+ int iEspionage = GC.getUnitInfo(eUnit).getEspionagePoints();
+ if (NO_GAMESPEED != GC.getGameINLINE().getGameSpeedType())
+ {
+ iEspionage *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getUnitGreatWorkPercent();
+ iEspionage /= 100;
+ }
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_ESPIONAGE_MISSION", iEspionage));
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumReligionInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getReligionSpreads(iI) > 0)
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_UNIT_CAN_SPREAD").c_str());
+ CvWString szReligion;
+ szReligion.Format(L"%s", GC.getReligionInfo((ReligionTypes) iI).getDescription());
+ setListHelp(szBuffer, szTempBuffer, szReligion, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumCorporationInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getCorporationSpreads(iI) > 0)
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_UNIT_CAN_EXPAND").c_str());
+ CvWString szCorporation;
+ szCorporation.Format(L"%s", GC.getCorporationInfo((CorporationTypes) iI).getDescription());
+ setListHelp(szBuffer, szTempBuffer, szCorporation, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumSpecialistInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getGreatPeoples(iI))
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_UNIT_CAN_JOIN").c_str());
+ CvWString szSpecialistLink = CvWString::format(L"%s", GC.getSpecialistInfo((SpecialistTypes) iI).getDescription());
+ setListHelp(szBuffer, szTempBuffer, szSpecialistLink.GetCString(), L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumBuildingInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getBuildings(iI) || GC.getUnitInfo(eUnit).getForceBuildings(iI))
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_UNIT_CAN_CONSTRUCT").c_str());
+ CvWString szBuildingLink = CvWString::format(L"%s", GC.getBuildingInfo((BuildingTypes) iI).getDescription());
+ setListHelp(szBuffer, szTempBuffer, szBuildingLink.GetCString(), L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ if (GC.getUnitInfo(eUnit).getCargoSpace() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_CARGO_SPACE", GC.getUnitInfo(eUnit).getCargoSpace()));
+
+ if (GC.getUnitInfo(eUnit).getSpecialCargo() != NO_SPECIALUNIT)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_CARRIES", GC.getSpecialUnitInfo((SpecialUnitTypes) GC.getUnitInfo(eUnit).getSpecialCargo()).getTextKeyWide()));
+ }
+ }
+
+ szTempBuffer.Format(L"%s%s ", NEWLINE, gDLL->getText("TXT_KEY_UNIT_CANNOT_ENTER").GetCString());
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumTerrainInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getTerrainImpassable(iI))
+ {
+ CvWString szTerrain;
+ TechTypes eTech = (TechTypes)GC.getUnitInfo(eUnit).getTerrainPassableTech(iI);
+ if (NO_TECH == eTech)
+ {
+ szTerrain.Format(L"%s", GC.getTerrainInfo((TerrainTypes)iI).getDescription());
+ }
+ else
+ {
+ szTerrain = gDLL->getText("TXT_KEY_TERRAIN_UNTIL_TECH", GC.getTerrainInfo((TerrainTypes)iI).getTextKeyWide(), GC.getTechInfo(eTech).getTextKeyWide());
+ }
+ setListHelp(szBuffer, szTempBuffer, szTerrain, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumFeatureInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getFeatureImpassable(iI))
+ {
+ CvWString szFeature;
+ TechTypes eTech = (TechTypes)GC.getUnitInfo(eUnit).getTerrainPassableTech(iI);
+ if (NO_TECH == eTech)
+ {
+ szFeature.Format(L"%s", GC.getFeatureInfo((FeatureTypes)iI).getDescription());
+ }
+ else
+ {
+ szFeature = gDLL->getText("TXT_KEY_TERRAIN_UNTIL_TECH", GC.getFeatureInfo((FeatureTypes)iI).getTextKeyWide(), GC.getTechInfo(eTech).getTextKeyWide());
+ }
+ setListHelp(szBuffer, szTempBuffer, szFeature, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ if (GC.getUnitInfo(eUnit).isInvisible())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_INVISIBLE_ALL"));
+ }
+ else if (GC.getUnitInfo(eUnit).getInvisibleType() != NO_INVISIBLE)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_INVISIBLE_MOST"));
+ }
+
+ for (iI = 0; iI < GC.getUnitInfo(eUnit).getNumSeeInvisibleTypes(); ++iI)
+ {
+ if (bCivilopediaText || (GC.getUnitInfo(eUnit).getSeeInvisibleType(iI) != GC.getUnitInfo(eUnit).getInvisibleType()))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_SEE_INVISIBLE", GC.getInvisibleInfo((InvisibleTypes) GC.getUnitInfo(eUnit).getSeeInvisibleType(iI)).getTextKeyWide()));
+ }
+ }
+
+ if (GC.getUnitInfo(eUnit).isCanMoveImpassable())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_CAN_MOVE_IMPASSABLE"));
+ }
+
+
+ if (GC.getUnitInfo(eUnit).isNoBadGoodies())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_NO_BAD_GOODIES"));
+ }
+
+ if (GC.getUnitInfo(eUnit).isHiddenNationality())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_HIDDEN_NATIONALITY"));
+ }
+
+ if (GC.getUnitInfo(eUnit).isAlwaysHostile())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_ALWAYS_HOSTILE"));
+ }
+
+ if (GC.getUnitInfo(eUnit).isOnlyDefensive())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_ONLY_DEFENSIVE"));
+ }
+
+ if (GC.getUnitInfo(eUnit).isNoCapture())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_CANNOT_CAPTURE"));
+ }
+
+ if (GC.getUnitInfo(eUnit).isRivalTerritory())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_EXPLORE_RIVAL"));
+ }
+
+ if (GC.getUnitInfo(eUnit).isFound())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_FOUND_CITY"));
+ }
+
+ iCount = 0;
+
+ for (iI = 0; iI < GC.getNumBuildInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getBuilds(iI))
+ {
+ iCount++;
+ }
+ }
+
+ if (iCount > ((GC.getNumBuildInfos() * 3) / 4))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_IMPROVE_PLOTS"));
+ }
+ else
+ {
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumBuildInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getBuilds(iI))
+ {
+ szTempBuffer.Format(L"%s%s ", NEWLINE, gDLL->getText("TXT_KEY_UNIT_CAN").c_str());
+ setListHelp(szBuffer, szTempBuffer, GC.getBuildInfo((BuildTypes) iI).getDescription(), L", ", bFirst);
+ bFirst = false;
+ }
+ }
+ }
+
+ if (GC.getUnitInfo(eUnit).getNukeRange() != -1)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_CAN_NUKE"));
+ }
+
+ if (GC.getUnitInfo(eUnit).isCounterSpy())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_EXPOSE_SPIES"));
+ }
+
+ if ((GC.getUnitInfo(eUnit).getFirstStrikes() + GC.getUnitInfo(eUnit).getChanceFirstStrikes()) > 0)
+ {
+ if (GC.getUnitInfo(eUnit).getChanceFirstStrikes() == 0)
+ {
+ if (GC.getUnitInfo(eUnit).getFirstStrikes() == 1)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_ONE_FIRST_STRIKE"));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_NUM_FIRST_STRIKES", GC.getUnitInfo(eUnit).getFirstStrikes()));
+ }
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_FIRST_STRIKE_CHANCES", GC.getUnitInfo(eUnit).getFirstStrikes(), GC.getUnitInfo(eUnit).getFirstStrikes() + GC.getUnitInfo(eUnit).getChanceFirstStrikes()));
+ }
+ }
+
+ if (GC.getUnitInfo(eUnit).isFirstStrikeImmune())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_IMMUNE_FIRST_STRIKES"));
+ }
+
+ if (GC.getUnitInfo(eUnit).isNoDefensiveBonus())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_NO_DEFENSE_BONUSES"));
+ }
+
+ if (GC.getUnitInfo(eUnit).isFlatMovementCost())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_FLAT_MOVEMENT"));
+ }
+
+ if (GC.getUnitInfo(eUnit).isIgnoreTerrainCost())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_IGNORE_TERRAIN"));
+ }
+
+ if (GC.getUnitInfo(eUnit).getInterceptionProbability() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_INTERCEPT_AIRCRAFT", GC.getUnitInfo(eUnit).getInterceptionProbability()));
+ }
+
+ if (GC.getUnitInfo(eUnit).getEvasionProbability() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_EVADE_INTERCEPTION", GC.getUnitInfo(eUnit).getEvasionProbability()));
+ }
+
+ if (GC.getUnitInfo(eUnit).getWithdrawalProbability() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_WITHDRAWL_PROBABILITY", GC.getUnitInfo(eUnit).getWithdrawalProbability()));
+ }
+
+ if (GC.getUnitInfo(eUnit).getCombatLimit() < GC.getMAX_HIT_POINTS() && GC.getUnitInfo(eUnit).getCombat() > 0 && !GC.getUnitInfo(eUnit).isOnlyDefensive())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_COMBAT_LIMIT", (100 * GC.getUnitInfo(eUnit).getCombatLimit()) / GC.getMAX_HIT_POINTS()));
+ }
+
+ if (GC.getUnitInfo(eUnit).getCollateralDamage() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_COLLATERAL_DAMAGE", ( 100 * GC.getUnitInfo(eUnit).getCollateralDamageLimit() / GC.getMAX_HIT_POINTS())));
+ }
+
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getUnitCombatCollateralImmune(iI))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_COLLATERAL_IMMUNE", GC.getUnitCombatInfo((UnitCombatTypes)iI).getTextKeyWide()));
+ }
+ }
+
+ if (GC.getUnitInfo(eUnit).getCityAttackModifier() == GC.getUnitInfo(eUnit).getCityDefenseModifier())
+ {
+ if (GC.getUnitInfo(eUnit).getCityAttackModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_CITY_STRENGTH_MOD", GC.getUnitInfo(eUnit).getCityAttackModifier()));
+ }
+ }
+ else
+ {
+ if (GC.getUnitInfo(eUnit).getCityAttackModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_CITY_ATTACK_MOD", GC.getUnitInfo(eUnit).getCityAttackModifier()));
+ }
+
+ if (GC.getUnitInfo(eUnit).getCityDefenseModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_CITY_DEFENSE_MOD", GC.getUnitInfo(eUnit).getCityDefenseModifier()));
+ }
+ }
+
+ if (GC.getUnitInfo(eUnit).getAnimalCombatModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_ANIMAL_COMBAT_MOD", GC.getUnitInfo(eUnit).getAnimalCombatModifier()));
+ }
+
+ if (GC.getUnitInfo(eUnit).getDropRange() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_PARADROP_RANGE", GC.getUnitInfo(eUnit).getDropRange()));
+ }
+
+ if (GC.getUnitInfo(eUnit).getHillsDefenseModifier() == GC.getUnitInfo(eUnit).getHillsAttackModifier())
+ {
+ if (GC.getUnitInfo(eUnit).getHillsAttackModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_HILLS_STRENGTH", GC.getUnitInfo(eUnit).getHillsAttackModifier()));
+ }
+ }
+ else
+ {
+ if (GC.getUnitInfo(eUnit).getHillsAttackModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_HILLS_ATTACK", GC.getUnitInfo(eUnit).getHillsAttackModifier()));
+ }
+
+ if (GC.getUnitInfo(eUnit).getHillsDefenseModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_HILLS_DEFENSE", GC.getUnitInfo(eUnit).getHillsDefenseModifier()));
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumTerrainInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getTerrainDefenseModifier(iI) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_DEFENSE", GC.getUnitInfo(eUnit).getTerrainDefenseModifier(iI), GC.getTerrainInfo((TerrainTypes) iI).getTextKeyWide()));
+ }
+
+ if (GC.getUnitInfo(eUnit).getTerrainAttackModifier(iI) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_ATTACK", GC.getUnitInfo(eUnit).getTerrainAttackModifier(iI), GC.getTerrainInfo((TerrainTypes) iI).getTextKeyWide()));
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumFeatureInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getFeatureDefenseModifier(iI) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_DEFENSE", GC.getUnitInfo(eUnit).getFeatureDefenseModifier(iI), GC.getFeatureInfo((FeatureTypes) iI).getTextKeyWide()));
+ }
+
+ if (GC.getUnitInfo(eUnit).getFeatureAttackModifier(iI) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_ATTACK", GC.getUnitInfo(eUnit).getFeatureAttackModifier(iI), GC.getFeatureInfo((FeatureTypes) iI).getTextKeyWide()));
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getUnitClassAttackModifier(iI) == GC.getUnitInfo(eUnit).getUnitClassDefenseModifier(iI))
+ {
+ if (GC.getUnitInfo(eUnit).getUnitClassAttackModifier(iI) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_MOD_VS_TYPE", GC.getUnitInfo(eUnit).getUnitClassAttackModifier(iI), GC.getUnitClassInfo((UnitClassTypes)iI).getTextKeyWide()));
+ }
+ }
+ else
+ {
+ if (GC.getUnitInfo(eUnit).getUnitClassAttackModifier(iI) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_ATTACK_MOD_VS_CLASS", GC.getUnitInfo(eUnit).getUnitClassAttackModifier(iI), GC.getUnitClassInfo((UnitClassTypes)iI).getTextKeyWide()));
+ }
+
+ if (GC.getUnitInfo(eUnit).getUnitClassDefenseModifier(iI) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_DEFENSE_MOD_VS_CLASS", GC.getUnitInfo(eUnit).getUnitClassDefenseModifier(iI), GC.getUnitClassInfo((UnitClassTypes) iI).getTextKeyWide()));
+ }
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getUnitCombatModifier(iI) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_MOD_VS_TYPE", GC.getUnitInfo(eUnit).getUnitCombatModifier(iI), GC.getUnitCombatInfo((UnitCombatTypes) iI).getTextKeyWide()));
+ }
+ }
+
+ for (iI = 0; iI < NUM_DOMAIN_TYPES; ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getDomainModifier(iI) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_MOD_VS_TYPE_NO_LINK", GC.getUnitInfo(eUnit).getDomainModifier(iI), GC.getDomainInfo((DomainTypes)iI).getTextKeyWide()));
+ }
+ }
+
+ szTempBuffer.clear();
+ bFirst = true;
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getTargetUnitClass(iI))
+ {
+ if (bFirst)
+ {
+ bFirst = false;
+ }
+ else
+ {
+ szTempBuffer += L", ";
+ }
+
+ szTempBuffer += CvWString::format(L"%s", GC.getUnitClassInfo((UnitClassTypes)iI).getDescription());
+ }
+ }
+
+ if (!bFirst)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_TARGETS_UNIT_FIRST", szTempBuffer.GetCString()));
+ }
+
+ szTempBuffer.clear();
+ bFirst = true;
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getDefenderUnitClass(iI))
+ {
+ if (bFirst)
+ {
+ bFirst = false;
+ }
+ else
+ {
+ szTempBuffer += L", ";
+ }
+
+ szTempBuffer += CvWString::format(L"%s", GC.getUnitClassInfo((UnitClassTypes)iI).getDescription());
+ }
+ }
+
+ if (!bFirst)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_DEFENDS_UNIT_FIRST", szTempBuffer.GetCString()));
+ }
+
+ szTempBuffer.clear();
+ bFirst = true;
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getTargetUnitCombat(iI))
+ {
+ if (bFirst)
+ {
+ bFirst = false;
+ }
+ else
+ {
+ szTempBuffer += L", ";
+ }
+
+ szTempBuffer += CvWString::format(L"%s", GC.getUnitCombatInfo((UnitCombatTypes)iI).getDescription());
+ }
+ }
+
+ if (!bFirst)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_TARGETS_UNIT_FIRST", szTempBuffer.GetCString()));
+ }
+
+ szTempBuffer.clear();
+ bFirst = true;
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getDefenderUnitCombat(iI))
+ {
+ if (bFirst)
+ {
+ bFirst = false;
+ }
+ else
+ {
+ szTempBuffer += L", ";
+ }
+
+ szTempBuffer += CvWString::format(L"%s", GC.getUnitCombatInfo((UnitCombatTypes)iI).getDescription());
+ }
+ }
+
+ if (!bFirst)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_DEFENDS_UNIT_FIRST", szTempBuffer.GetCString()));
+ }
+
+ szTempBuffer.clear();
+ bFirst = true;
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getFlankingStrikeUnitClass(iI) > 0)
+ {
+ if (bFirst)
+ {
+ bFirst = false;
+ }
+ else
+ {
+ szTempBuffer += L", ";
+ }
+
+ szTempBuffer += CvWString::format(L"%s", GC.getUnitClassInfo((UnitClassTypes)iI).getDescription());
+ }
+ }
+
+ if (!bFirst)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_FLANKING_STRIKES", szTempBuffer.GetCString()));
+ }
+
+ if (GC.getUnitInfo(eUnit).getBombRate() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_BOMB_RATE", ((GC.getUnitInfo(eUnit).getBombRate() * 100) / GC.getMAX_CITY_DEFENSE_DAMAGE())));
+ }
+
+ if (GC.getUnitInfo(eUnit).getBombardRate() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_BOMBARD_RATE", ((GC.getUnitInfo(eUnit).getBombardRate() * 100) / GC.getMAX_CITY_DEFENSE_DAMAGE())));
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumPromotionInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getFreePromotions(iI))
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_UNIT_STARTS_WITH").c_str());
+ setListHelp(szBuffer, szTempBuffer, CvWString::format(L"%s", GC.getPromotionInfo((PromotionTypes) iI).getDescription()), L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ if (GC.getUnitInfo(eUnit).getExtraCost() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_EXTRA_COST", GC.getUnitInfo(eUnit).getExtraCost()));
+ }
+
+ if (bCivilopediaText)
+ {
+ // Trait
+ for (int i = 0; i < GC.getNumTraitInfos(); ++i)
+ {
+ if (GC.getUnitInfo(eUnit).getProductionTraits((TraitTypes)i) != 0)
+ {
+ if (GC.getUnitInfo(eUnit).getProductionTraits((TraitTypes)i) == 100)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_DOUBLE_SPEED_TRAIT", GC.getTraitInfo((TraitTypes)i).getTextKeyWide()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PRODUCTION_MODIFIER_TRAIT", GC.getUnitInfo(eUnit).getProductionTraits((TraitTypes)i), GC.getTraitInfo((TraitTypes)i).getTextKeyWide()));
+ }
+ }
+ }
+ }
+
+ if (!CvWString(GC.getUnitInfo(eUnit).getHelp()).empty())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(GC.getUnitInfo(eUnit).getHelp());
+ }
+}
+
+
+void CvGameTextMgr::setUnitHelp(CvWStringBuffer &szBuffer, UnitTypes eUnit, bool bCivilopediaText, bool bStrategyText, bool bTechChooserText, CvCity* pCity)
+{
+ PROFILE_FUNC();
+
+ CvWString szTempBuffer;
+ PlayerTypes ePlayer;
+ bool bFirst;
+ int iProduction;
+ int iI;
+
+ if (NO_UNIT == eUnit)
+ {
+ return;
+ }
+
+ if (pCity != NULL)
+ {
+ ePlayer = pCity->getOwnerINLINE();
+ }
+ else
+ {
+ ePlayer = GC.getGameINLINE().getActivePlayer();
+ }
+
+ if (!bCivilopediaText)
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_UNIT_TEXT"), GC.getUnitInfo(eUnit).getDescription());
+ szBuffer.append(szTempBuffer);
+
+ if (GC.getUnitInfo(eUnit).getUnitCombatType() != NO_UNITCOMBAT)
+ {
+ szTempBuffer.Format(L" (%s)", GC.getUnitCombatInfo((UnitCombatTypes) GC.getUnitInfo(eUnit).getUnitCombatType()).getDescription());
+ szBuffer.append(szTempBuffer);
+ }
+ }
+
+ // test for unique unit
+ UnitClassTypes eUnitClass = (UnitClassTypes)GC.getUnitInfo(eUnit).getUnitClassType();
+ UnitTypes eDefaultUnit = (UnitTypes)GC.getUnitClassInfo(eUnitClass).getDefaultUnitIndex();
+
+ if (NO_UNIT != eDefaultUnit && eDefaultUnit != eUnit)
+ {
+ for (iI = 0; iI < GC.getNumCivilizationInfos(); ++iI)
+ {
+ UnitTypes eUniqueUnit = (UnitTypes)GC.getCivilizationInfo((CivilizationTypes)iI).getCivilizationUnits((int)eUnitClass);
+ if (eUniqueUnit == eUnit)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIQUE_UNIT", GC.getCivilizationInfo((CivilizationTypes)iI).getTextKeyWide()));
+ }
+ }
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_REPLACES_UNIT", GC.getUnitInfo(eDefaultUnit).getTextKeyWide()));
+ }
+
+ if (isWorldUnitClass(eUnitClass))
+ {
+ if (pCity == NULL)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_WORLD_UNIT_ALLOWED", GC.getUnitClassInfo(eUnitClass).getMaxGlobalInstances()));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_WORLD_UNIT_LEFT", (GC.getUnitClassInfo(eUnitClass).getMaxGlobalInstances() - (ePlayer != NO_PLAYER ? GC.getGameINLINE().getUnitClassCreatedCount(eUnitClass) + GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getUnitClassMaking(eUnitClass) : 0))));
+ }
+ }
+
+ if (isTeamUnitClass(eUnitClass))
+ {
+ if (pCity == NULL)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_TEAM_UNIT_ALLOWED", GC.getUnitClassInfo(eUnitClass).getMaxTeamInstances()));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_TEAM_UNIT_LEFT", (GC.getUnitClassInfo(eUnitClass).getMaxTeamInstances() - (ePlayer != NO_PLAYER ? GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getUnitClassCountPlusMaking(eUnitClass) : 0))));
+ }
+ }
+
+ if (isNationalUnitClass(eUnitClass))
+ {
+ if (pCity == NULL)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_NATIONAL_UNIT_ALLOWED", GC.getUnitClassInfo(eUnitClass).getMaxPlayerInstances()));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_NATIONAL_UNIT_LEFT", (GC.getUnitClassInfo(eUnitClass).getMaxPlayerInstances() - (ePlayer != NO_PLAYER ? GET_PLAYER(ePlayer).getUnitClassCountPlusMaking(eUnitClass) : 0))));
+ }
+ }
+
+ if (0 != GC.getUnitClassInfo(eUnitClass).getInstanceCostModifier())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_INSTANCE_COST_MOD", GC.getUnitClassInfo(eUnitClass).getInstanceCostModifier()));
+ }
+
+ setBasicUnitHelp(szBuffer, eUnit, bCivilopediaText);
+
+ if ((pCity == NULL) || !(pCity->canTrain(eUnit)))
+ {
+ if (pCity != NULL)
+ {
+ if (GC.getGameINLINE().isNoNukes())
+ {
+ if (GC.getUnitInfo(eUnit).getNukeRange() != -1)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_NO_NUKES"));
+ }
+ }
+ }
+
+ if (GC.getUnitInfo(eUnit).getHolyCity() != NO_RELIGION)
+ {
+ if ((pCity == NULL) || !(pCity->isHolyCity((ReligionTypes)(GC.getUnitInfo(eUnit).getHolyCity()))))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_REQUIRES_HOLY_CITY", GC.getReligionInfo((ReligionTypes)(GC.getUnitInfo(eUnit).getHolyCity())).getChar()));
+ }
+ }
+
+ bFirst = true;
+
+ if (GC.getUnitInfo(eUnit).getSpecialUnitType() != NO_SPECIALUNIT)
+ {
+ if ((pCity == NULL) || !(GC.getGameINLINE().isSpecialUnitValid((SpecialUnitTypes)(GC.getUnitInfo(eUnit).getSpecialUnitType()))))
+ {
+ for (iI = 0; iI < GC.getNumProjectInfos(); ++iI)
+ {
+ if (GC.getProjectInfo((ProjectTypes)iI).getEveryoneSpecialUnit() == GC.getUnitInfo(eUnit).getSpecialUnitType())
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_REQUIRES").c_str());
+ CvWString szProject;
+ szProject.Format(L"%s", GC.getProjectInfo((ProjectTypes)iI).getDescription());
+ setListHelp(szBuffer, szTempBuffer, szProject, gDLL->getText("TXT_KEY_OR").c_str(), bFirst);
+ bFirst = false;
+ }
+ }
+ }
+ }
+
+ if (!bFirst)
+ {
+ szBuffer.append(ENDCOLR);
+ }
+
+ bFirst = true;
+
+ if (GC.getUnitInfo(eUnit).getNukeRange() != -1)
+ {
+ if (NULL == pCity || !GC.getGameINLINE().isNukesValid())
+ {
+ for (iI = 0; iI < GC.getNumProjectInfos(); ++iI)
+ {
+ if (GC.getProjectInfo((ProjectTypes)iI).isAllowsNukes())
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_REQUIRES").c_str());
+ CvWString szProject;
+ szProject.Format(L"%s", GC.getProjectInfo((ProjectTypes)iI).getDescription());
+ setListHelp(szBuffer, szTempBuffer, szProject, gDLL->getText("TXT_KEY_OR").c_str(), bFirst);
+ bFirst = false;
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumBuildingInfos(); ++iI)
+ {
+ if (GC.getBuildingInfo((BuildingTypes)iI).isAllowsNukes())
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_REQUIRES").c_str());
+ CvWString szBuilding;
+ szBuilding.Format(L"%s", GC.getBuildingInfo((BuildingTypes)iI).getDescription());
+ setListHelp(szBuffer, szTempBuffer, szBuilding, gDLL->getText("TXT_KEY_OR").c_str(), bFirst);
+ bFirst = false;
+ }
+ }
+ }
+ }
+
+ if (!bFirst)
+ {
+ szBuffer.append(ENDCOLR);
+ }
+
+ if (!bCivilopediaText)
+ {
+ if (GC.getUnitInfo(eUnit).getPrereqBuilding() != NO_BUILDING)
+ {
+ if ((pCity == NULL) || (pCity->getNumBuilding((BuildingTypes)(GC.getUnitInfo(eUnit).getPrereqBuilding())) <= 0))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_REQUIRES_STRING", GC.getBuildingInfo((BuildingTypes)(GC.getUnitInfo(eUnit).getPrereqBuilding())).getTextKeyWide()));
+ }
+ }
+
+ if (!bTechChooserText)
+ {
+ if (GC.getUnitInfo(eUnit).getPrereqAndTech() != NO_TECH)
+ {
+ if (GC.getGameINLINE().getActivePlayer() == NO_PLAYER || !(GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isHasTech((TechTypes)(GC.getUnitInfo(eUnit).getPrereqAndTech()))))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_REQUIRES_STRING", GC.getTechInfo((TechTypes)(GC.getUnitInfo(eUnit).getPrereqAndTech())).getTextKeyWide()));
+ }
+ }
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNUM_UNIT_AND_TECH_PREREQS(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getPrereqAndTechs(iI) != NO_TECH)
+ {
+ if (bTechChooserText || GC.getGameINLINE().getActivePlayer() == NO_PLAYER || !(GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isHasTech((TechTypes)(GC.getUnitInfo(eUnit).getPrereqAndTechs(iI)))))
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_REQUIRES").c_str());
+ setListHelp(szBuffer, szTempBuffer, GC.getTechInfo(((TechTypes)(GC.getUnitInfo(eUnit).getPrereqAndTechs(iI)))).getDescription(), gDLL->getText("TXT_KEY_AND").c_str(), bFirst);
+ bFirst = false;
+ }
+ }
+ }
+
+ if (!bFirst)
+ {
+ szBuffer.append(ENDCOLR);
+ }
+
+ if (GC.getUnitInfo(eUnit).getPrereqAndBonus() != NO_BONUS)
+ {
+ if ((pCity == NULL) || !(pCity->hasBonus((BonusTypes)GC.getUnitInfo(eUnit).getPrereqAndBonus())))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_REQUIRES_STRING", GC.getBonusInfo((BonusTypes)(GC.getUnitInfo(eUnit).getPrereqAndBonus())).getTextKeyWide()));
+ }
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNUM_UNIT_PREREQ_OR_BONUSES(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getPrereqOrBonuses(iI) != NO_BONUS)
+ {
+ if ((pCity == NULL) || !(pCity->hasBonus((BonusTypes)GC.getUnitInfo(eUnit).getPrereqOrBonuses(iI))))
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_REQUIRES").c_str());
+ setListHelp(szBuffer, szTempBuffer, GC.getBonusInfo((BonusTypes) GC.getUnitInfo(eUnit).getPrereqOrBonuses(iI)).getDescription(), gDLL->getText("TXT_KEY_OR").c_str(), bFirst);
+ bFirst = false;
+ }
+ }
+ }
+
+ if (!bFirst)
+ {
+ szBuffer.append(ENDCOLR);
+ }
+ }
+ }
+
+ if (!bCivilopediaText && GC.getGameINLINE().getActivePlayer() != NO_PLAYER)
+ {
+ if (pCity == NULL)
+ {
+ szTempBuffer.Format(L"%s%d%c", NEWLINE, GET_PLAYER(ePlayer).getProductionNeeded(eUnit), GC.getYieldInfo(YIELD_PRODUCTION).getChar());
+ szBuffer.append(szTempBuffer);
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_TURNS", pCity->getProductionTurnsLeft(eUnit, ((gDLL->ctrlKey() || !(gDLL->shiftKey())) ? 0 : pCity->getOrderQueueLength())), pCity->getProductionNeeded(eUnit), GC.getYieldInfo(YIELD_PRODUCTION).getChar()));
+
+ iProduction = pCity->getUnitProduction(eUnit);
+
+ if (iProduction > 0)
+ {
+ szTempBuffer.Format(L" - %d/%d%c", iProduction, pCity->getProductionNeeded(eUnit), GC.getYieldInfo(YIELD_PRODUCTION).getChar());
+ szBuffer.append(szTempBuffer);
+ }
+ else
+ {
+ szTempBuffer.Format(L" - %d%c", pCity->getProductionNeeded(eUnit), GC.getYieldInfo(YIELD_PRODUCTION).getChar());
+ szBuffer.append(szTempBuffer);
+ }
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumBonusInfos(); ++iI)
+ {
+ if (GC.getUnitInfo(eUnit).getBonusProductionModifier(iI) != 0)
+ {
+ if (pCity != NULL)
+ {
+ if (pCity->hasBonus((BonusTypes)iI))
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_COLOR_POSITIVE"));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_COLOR_NEGATIVE"));
+ }
+ }
+ if (!bCivilopediaText)
+ {
+ szBuffer.append(L" (");
+ }
+ else
+ {
+ szTempBuffer.Format(L"%s%c", NEWLINE, gDLL->getSymbolID(BULLET_CHAR), szTempBuffer);
+ szBuffer.append(szTempBuffer);
+ }
+ if (GC.getUnitInfo(eUnit).getBonusProductionModifier(iI) == 100)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_DOUBLE_SPEED", GC.getBonusInfo((BonusTypes)iI).getTextKeyWide()));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_BUILDS_FASTER", GC.getUnitInfo(eUnit).getBonusProductionModifier(iI), GC.getBonusInfo((BonusTypes)iI).getTextKeyWide()));
+ }
+ if (!bCivilopediaText)
+ {
+ szBuffer.append(L")");
+ }
+ if (pCity != NULL)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_COLOR_REVERT"));
+ }
+ }
+ }
+
+ if (bStrategyText)
+ {
+ if (!CvWString(GC.getUnitInfo(eUnit).getStrategy()).empty())
+ {
+ if ((ePlayer == NO_PLAYER) || GET_PLAYER(ePlayer).isOption(PLAYEROPTION_ADVISOR_HELP))
+ {
+ szBuffer.append(SEPARATOR);
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_SIDS_TIPS"));
+ szBuffer.append(L'\"');
+ szBuffer.append(GC.getUnitInfo(eUnit).getStrategy());
+ szBuffer.append(L'\"');
+ }
+ }
+ }
+
+ if (bCivilopediaText)
+ {
+ if (eDefaultUnit == eUnit)
+ {
+ for (iI = 0; iI < GC.getNumUnitInfos(); ++iI)
+ {
+ if (iI != eUnit)
+ {
+ if (eUnitClass == GC.getUnitInfo((UnitTypes)iI).getUnitClassType())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_REPLACED_BY_UNIT", GC.getUnitInfo((UnitTypes)iI).getTextKeyWide()));
+ }
+ }
+ }
+ }
+ }
+
+ if (pCity != NULL)
+ {
+ if ((gDLL->getChtLvl() > 0) && gDLL->ctrlKey())
+ {
+ szBuffer.append(NEWLINE);
+ for (int iUnitAI = 0; iUnitAI < NUM_UNITAI_TYPES; iUnitAI++)
+ {
+ int iTempValue = GET_PLAYER(pCity->getOwner()).AI_unitValue(eUnit, (UnitAITypes)iUnitAI, pCity->area());
+ if (iTempValue != 0)
+ {
+ CvWString szTempString;
+ getUnitAIString(szTempString, (UnitAITypes)iUnitAI);
+ szBuffer.append(CvWString::format(L"(%s : %d) ", szTempString.GetCString(), iTempValue));
+ }
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::setBuildingHelp(CvWStringBuffer &szBuffer, BuildingTypes eBuilding, bool bCivilopediaText, bool bStrategyText, bool bTechChooserText, CvCity* pCity)
+{
+ PROFILE_FUNC();
+
+ CvWString szFirstBuffer;
+ CvWString szTempBuffer;
+ BuildingTypes eLoopBuilding;
+ UnitTypes eGreatPeopleUnit;
+ PlayerTypes ePlayer;
+ bool bFirst;
+ int iProduction;
+ int iLast;
+ int iI;
+
+ if (NO_BUILDING == eBuilding)
+ {
+ return;
+ }
+
+ CvBuildingInfo& kBuilding = GC.getBuildingInfo(eBuilding);
+
+
+ if (pCity != NULL)
+ {
+ ePlayer = pCity->getOwnerINLINE();
+ }
+ else
+ {
+ ePlayer = GC.getGameINLINE().getActivePlayer();
+ }
+
+ if (!bCivilopediaText)
+ {
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_BUILDING_TEXT"), kBuilding.getDescription());
+ szBuffer.append(szTempBuffer);
+
+ int iHappiness;
+ if (NULL != pCity)
+ {
+ iHappiness = pCity->getBuildingHappiness(eBuilding);
+ }
+ else
+ {
+ iHappiness = kBuilding.getHappiness();
+ }
+
+ if (iHappiness != 0)
+ {
+ szTempBuffer.Format(L", +%d%c", abs(iHappiness), ((iHappiness > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR)));
+ szBuffer.append(szTempBuffer);
+ }
+
+ int iHealth;
+ if (NULL != pCity)
+ {
+ iHealth = pCity->getBuildingGoodHealth(eBuilding);
+ }
+ else
+ {
+ iHealth = kBuilding.getHealth();
+ if (ePlayer != NO_PLAYER)
+ {
+ if (eBuilding == GC.getCivilizationInfo(GET_PLAYER(ePlayer).getCivilizationType()).getCivilizationBuildings(kBuilding.getBuildingClassType()))
+ {
+ iHealth += GET_PLAYER(ePlayer).getExtraBuildingHealth(eBuilding);
+ }
+ }
+ }
+ if (iHealth != 0)
+ {
+ szTempBuffer.Format(L", +%d%c", abs(iHealth), ((iHealth > 0) ? gDLL->getSymbolID(HEALTHY_CHAR): gDLL->getSymbolID(UNHEALTHY_CHAR)));
+ szBuffer.append(szTempBuffer);
+ }
+
+ iHealth = 0;
+ if (NULL != pCity)
+ {
+ iHealth = pCity->getBuildingBadHealth(eBuilding);
+ }
+ if (iHealth != 0)
+ {
+ szTempBuffer.Format(L", +%d%c", abs(iHealth), ((iHealth > 0) ? gDLL->getSymbolID(HEALTHY_CHAR): gDLL->getSymbolID(UNHEALTHY_CHAR)));
+ szBuffer.append(szTempBuffer);
+ }
+
+ int aiYields[NUM_YIELD_TYPES];
+ for (iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ aiYields[iI] = kBuilding.getYieldChange(iI);
+
+ if (NULL != pCity)
+ {
+ aiYields[iI] += pCity->getBuildingYieldChange((BuildingClassTypes)kBuilding.getBuildingClassType(), (YieldTypes)iI);
+ }
+ }
+ setYieldChangeHelp(szBuffer, L", ", L"", L"", aiYields, false, false);
+
+ int aiCommerces[NUM_COMMERCE_TYPES];
+ for (int iI = 0; iI < NUM_COMMERCE_TYPES; ++iI)
+ {
+ if ((NULL != pCity) && (pCity->getNumBuilding(eBuilding) > 0))
+ {
+ aiCommerces[iI] = pCity->getBuildingCommerceByBuilding((CommerceTypes)iI, eBuilding);
+ }
+ else
+ {
+ aiCommerces[iI] = kBuilding.getCommerceChange(iI);
+ aiCommerces[iI] += kBuilding.getObsoleteSafeCommerceChange(iI);
+ }
+ }
+ setCommerceChangeHelp(szBuffer, L", ", L"", L"", aiCommerces, false, false);
+
+ setYieldChangeHelp(szBuffer, L", ", L"", L"", kBuilding.getYieldModifierArray(), true, bCivilopediaText);
+ setCommerceChangeHelp(szBuffer, L", ", L"", L"", kBuilding.getCommerceModifierArray(), true, bCivilopediaText);
+
+ if (kBuilding.getGreatPeopleRateChange() != 0)
+ {
+ szTempBuffer.Format(L", %s%d%c", ((kBuilding.getGreatPeopleRateChange() > 0) ? "+" : ""), kBuilding.getGreatPeopleRateChange(), gDLL->getSymbolID(GREAT_PEOPLE_CHAR));
+ szBuffer.append(szTempBuffer);
+
+ if (kBuilding.getGreatPeopleUnitClass() != NO_UNITCLASS)
+ {
+ if (ePlayer != NO_PLAYER)
+ {
+ eGreatPeopleUnit = ((UnitTypes)(GC.getCivilizationInfo(GET_PLAYER(ePlayer).getCivilizationType()).getCivilizationUnits(kBuilding.getGreatPeopleUnitClass())));
+ }
+ else
+ {
+ eGreatPeopleUnit = (UnitTypes)GC.getUnitClassInfo((UnitClassTypes)kBuilding.getGreatPeopleUnitClass()).getDefaultUnitIndex();
+ }
+
+ if (eGreatPeopleUnit != NO_UNIT)
+ {
+ szTempBuffer.Format(L" (%s)", GC.getUnitInfo(eGreatPeopleUnit).getDescription());
+ szBuffer.append(szTempBuffer);
+ }
+ }
+ }
+ }
+
+ // test for unique building
+ BuildingClassTypes eBuildingClass = (BuildingClassTypes)kBuilding.getBuildingClassType();
+ BuildingTypes eDefaultBuilding = (BuildingTypes)GC.getBuildingClassInfo(eBuildingClass).getDefaultBuildingIndex();
+
+ if (NO_BUILDING != eDefaultBuilding && eDefaultBuilding != eBuilding)
+ {
+ for (iI = 0; iI < GC.getNumCivilizationInfos(); ++iI)
+ {
+ BuildingTypes eUniqueBuilding = (BuildingTypes)GC.getCivilizationInfo((CivilizationTypes)iI).getCivilizationBuildings((int)eBuildingClass);
+ if (eUniqueBuilding == eBuilding)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIQUE_BUILDING", GC.getCivilizationInfo((CivilizationTypes)iI).getTextKeyWide()));
+ }
+ }
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_REPLACES_UNIT", GC.getBuildingInfo(eDefaultBuilding).getTextKeyWide()));
+ }
+
+ if (bCivilopediaText)
+ {
+ setYieldChangeHelp(szBuffer, L"", L"", L"", kBuilding.getYieldModifierArray(), true, bCivilopediaText);
+
+ setCommerceChangeHelp(szBuffer, L"", L"", L"", kBuilding.getCommerceModifierArray(), true, bCivilopediaText);
+ }
+ else
+ {
+ if (isWorldWonderClass((BuildingClassTypes)(kBuilding.getBuildingClassType())))
+ {
+ if (pCity == NULL || ePlayer == NO_PLAYER)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_WORLD_WONDER_ALLOWED", GC.getBuildingClassInfo((BuildingClassTypes) kBuilding.getBuildingClassType()).getMaxGlobalInstances()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_WORLD_WONDER_LEFT", (GC.getBuildingClassInfo((BuildingClassTypes) kBuilding.getBuildingClassType()).getMaxGlobalInstances() - GC.getGameINLINE().getBuildingClassCreatedCount((BuildingClassTypes)(kBuilding.getBuildingClassType())) - GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getBuildingClassMaking((BuildingClassTypes)(kBuilding.getBuildingClassType())))));
+ }
+ }
+
+ if (isTeamWonderClass((BuildingClassTypes)(kBuilding.getBuildingClassType())))
+ {
+ if (pCity == NULL || ePlayer == NO_PLAYER)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_TEAM_WONDER_ALLOWED", GC.getBuildingClassInfo((BuildingClassTypes) kBuilding.getBuildingClassType()).getMaxTeamInstances()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_TEAM_WONDER_LEFT", (GC.getBuildingClassInfo((BuildingClassTypes) kBuilding.getBuildingClassType()).getMaxTeamInstances() - GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getBuildingClassCountPlusMaking((BuildingClassTypes)(kBuilding.getBuildingClassType())))));
+ }
+ }
+
+ if (isNationalWonderClass((BuildingClassTypes)(kBuilding.getBuildingClassType())))
+ {
+ if (pCity == NULL || ePlayer == NO_PLAYER)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_NATIONAL_WONDER_ALLOWED", GC.getBuildingClassInfo((BuildingClassTypes) kBuilding.getBuildingClassType()).getMaxPlayerInstances()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_NATIONAL_WONDER_LEFT", (GC.getBuildingClassInfo((BuildingClassTypes) kBuilding.getBuildingClassType()).getMaxPlayerInstances() - GET_PLAYER(ePlayer).getBuildingClassCountPlusMaking((BuildingClassTypes)(kBuilding.getBuildingClassType())))));
+ }
+ }
+ }
+
+ if (kBuilding.getGlobalReligionCommerce() != NO_RELIGION)
+ {
+ szFirstBuffer = gDLL->getText("TXT_KEY_BUILDING_PER_CITY_WITH", GC.getReligionInfo((ReligionTypes) kBuilding.getGlobalReligionCommerce()).getChar());
+ setCommerceChangeHelp(szBuffer, L"", L"", szFirstBuffer, GC.getReligionInfo((ReligionTypes) kBuilding.getGlobalReligionCommerce()).getGlobalReligionCommerceArray());
+ }
+
+ if (NO_CORPORATION != kBuilding.getFoundsCorporation())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_FOUNDS_CORPORATION", GC.getCorporationInfo((CorporationTypes)kBuilding.getFoundsCorporation()).getTextKeyWide()));
+ }
+
+ if (kBuilding.getGlobalCorporationCommerce() != NO_CORPORATION)
+ {
+ szFirstBuffer = gDLL->getText("TXT_KEY_BUILDING_PER_CITY_WITH", GC.getCorporationInfo((CorporationTypes) kBuilding.getGlobalCorporationCommerce()).getChar());
+ setCommerceChangeHelp(szBuffer, L"", L"", szFirstBuffer, GC.getCorporationInfo((CorporationTypes) kBuilding.getGlobalCorporationCommerce()).getHeadquarterCommerceArray());
+ }
+
+ if (kBuilding.getNoBonus() != NO_BONUS)
+ {
+ CvBonusInfo& kBonus = GC.getBonusInfo((BonusTypes) kBuilding.getNoBonus());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_DISABLES", kBonus.getTextKeyWide(), kBonus.getChar()));
+ }
+
+ if (kBuilding.getFreeBonus() != NO_BONUS)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_PROVIDES", GC.getGameINLINE().getNumFreeBonuses(eBuilding), GC.getBonusInfo((BonusTypes) kBuilding.getFreeBonus()).getTextKeyWide(), GC.getBonusInfo((BonusTypes) kBuilding.getFreeBonus()).getChar()));
+
+ if (GC.getBonusInfo((BonusTypes)(kBuilding.getFreeBonus())).getHealth() != 0)
+ {
+ szTempBuffer.Format(L", +%d%c", abs(GC.getBonusInfo((BonusTypes) kBuilding.getFreeBonus()).getHealth()), ((GC.getBonusInfo((BonusTypes)(kBuilding.getFreeBonus())).getHealth() > 0) ? gDLL->getSymbolID(HEALTHY_CHAR): gDLL->getSymbolID(UNHEALTHY_CHAR)));
+ szBuffer.append(szTempBuffer);
+ }
+
+ if (GC.getBonusInfo((BonusTypes)(kBuilding.getFreeBonus())).getHappiness() != 0)
+ {
+ szTempBuffer.Format(L", +%d%c", abs(GC.getBonusInfo((BonusTypes) kBuilding.getFreeBonus()).getHappiness()), ((GC.getBonusInfo((BonusTypes)(kBuilding.getFreeBonus())).getHappiness() > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR)));
+ szBuffer.append(szTempBuffer);
+ }
+ }
+
+ if (kBuilding.getFreeBuildingClass() != NO_BUILDINGCLASS)
+ {
+ BuildingTypes eFreeBuilding;
+ if (ePlayer != NO_PLAYER)
+ {
+ eFreeBuilding = ((BuildingTypes)(GC.getCivilizationInfo(GET_PLAYER(ePlayer).getCivilizationType()).getCivilizationBuildings(kBuilding.getFreeBuildingClass())));
+ }
+ else
+ {
+ eFreeBuilding = (BuildingTypes)GC.getBuildingClassInfo((BuildingClassTypes)kBuilding.getFreeBuildingClass()).getDefaultBuildingIndex();
+ }
+
+ if (NO_BUILDING != eFreeBuilding)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_FREE_IN_CITY", GC.getBuildingInfo(eFreeBuilding).getTextKeyWide()));
+ }
+ }
+
+ if (kBuilding.getFreePromotion() != NO_PROMOTION)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_FREE_PROMOTION", GC.getPromotionInfo((PromotionTypes)(kBuilding.getFreePromotion())).getTextKeyWide()));
+ }
+
+ if (kBuilding.getCivicOption() != NO_CIVICOPTION)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_ENABLES_CIVICS", GC.getCivicOptionInfo((CivicOptionTypes)(kBuilding.getCivicOption())).getTextKeyWide()));
+ }
+
+ if (kBuilding.isPower())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_PROVIDES_POWER"));
+
+ if (kBuilding.isDirtyPower() && (GC.getDefineINT("DIRTY_POWER_HEALTH_CHANGE") != 0))
+ {
+ szTempBuffer.Format(L" (+%d%c)", abs(GC.getDefineINT("DIRTY_POWER_HEALTH_CHANGE")), ((GC.getDefineINT("DIRTY_POWER_HEALTH_CHANGE") > 0) ? gDLL->getSymbolID(HEALTHY_CHAR): gDLL->getSymbolID(UNHEALTHY_CHAR)));
+ szBuffer.append(szTempBuffer);
+ }
+ }
+
+ if (kBuilding.isAreaCleanPower())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_PROVIDES_AREA_CLEAN_POWER"));
+ }
+
+ if (kBuilding.isAreaBorderObstacle())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_BORDER_OBSTACLE"));
+ }
+
+ for (iI = 0; iI < GC.getNumVoteSourceInfos(); ++iI)
+ {
+ if (kBuilding.getVoteSourceType() == (VoteSourceTypes)iI)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_DIPLO_VOTE", GC.getVoteSourceInfo((VoteSourceTypes)iI).getTextKeyWide()));
+ }
+ }
+
+ if (kBuilding.isForceTeamVoteEligible())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_ELECTION_ELIGIBILITY"));
+ }
+
+ if (kBuilding.isCapital())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_CAPITAL"));
+ }
+
+ if (kBuilding.isGovernmentCenter())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_REDUCES_MAINTENANCE"));
+ }
+
+ if (kBuilding.isGoldenAge())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_GOLDEN_AGE"));
+ }
+
+ if (kBuilding.isAllowsNukes())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_ENABLES_NUKES"));
+ }
+
+ if (kBuilding.isMapCentering())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_CENTERS_MAP"));
+ }
+
+ if (kBuilding.isNoUnhappiness())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_NO_UNHAPPY"));
+ }
+
+ if (kBuilding.isNoUnhealthyPopulation())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_NO_UNHEALTHY_POP"));
+ }
+
+ if (kBuilding.isBuildingOnlyHealthy())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_NO_UNHEALTHY_BUILDINGS"));
+ }
+
+ if (kBuilding.getGreatPeopleRateModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_BIRTH_RATE_MOD", kBuilding.getGreatPeopleRateModifier()));
+ }
+
+ if (kBuilding.getGreatGeneralRateModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_GENERAL_RATE_MOD", kBuilding.getGreatGeneralRateModifier()));
+ }
+
+ if (kBuilding.getDomesticGreatGeneralRateModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_DOMESTIC_GREAT_GENERAL_MODIFIER", kBuilding.getDomesticGreatGeneralRateModifier()));
+ }
+
+ if (kBuilding.getGlobalGreatPeopleRateModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_BIRTH_RATE_MOD_ALL_CITIES", kBuilding.getGlobalGreatPeopleRateModifier()));
+ }
+
+ if (kBuilding.getAnarchyModifier() != 0)
+ {
+ if (-100 == kBuilding.getAnarchyModifier())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_NO_ANARCHY"));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_ANARCHY_MOD", kBuilding.getAnarchyModifier()));
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_ANARCHY_TIMER_MOD", kBuilding.getAnarchyModifier()));
+ }
+ }
+
+ if (kBuilding.getGoldenAgeModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_GOLDENAGE_MOD", kBuilding.getGoldenAgeModifier()));
+ }
+
+ if (kBuilding.getGlobalHurryModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_HURRY_MOD", kBuilding.getGlobalHurryModifier()));
+ }
+
+ if (kBuilding.getFreeExperience() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_FREE_XP_UNITS", kBuilding.getFreeExperience()));
+ }
+
+ if (kBuilding.getGlobalFreeExperience() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_FREE_XP_ALL_CITIES", kBuilding.getGlobalFreeExperience()));
+ }
+
+ if (kBuilding.getFoodKept() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_STORES_FOOD", kBuilding.getFoodKept()));
+ }
+
+ if (kBuilding.getAirlift() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_AIRLIFT", kBuilding.getAirlift()));
+ }
+
+ if (kBuilding.getAirModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_AIR_DAMAGE_MOD", kBuilding.getAirModifier()));
+ }
+
+ if (kBuilding.getAirUnitCapacity() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_AIR_UNIT_CAPACITY", kBuilding.getAirUnitCapacity()));
+ }
+
+ if (kBuilding.getNukeModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_NUKE_DAMAGE_MOD", kBuilding.getNukeModifier()));
+ }
+
+ if (kBuilding.getNukeExplosionRand() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_NUKE_EXPLOSION_CHANCE"));
+ }
+
+ if (kBuilding.getFreeSpecialist() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_FREE_SPECIALISTS", kBuilding.getFreeSpecialist()));
+ }
+
+ if (kBuilding.getAreaFreeSpecialist() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_FREE_SPECIALISTS_CONT", kBuilding.getAreaFreeSpecialist()));
+ }
+
+ if (kBuilding.getGlobalFreeSpecialist() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_FREE_SPECIALISTS_ALL_CITIES", kBuilding.getGlobalFreeSpecialist()));
+ }
+
+ if (kBuilding.getMaintenanceModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_MAINT_MOD", kBuilding.getMaintenanceModifier()));
+ }
+
+ if (kBuilding.getHurryAngerModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_HURRY_ANGER_MOD", kBuilding.getHurryAngerModifier()));
+ }
+
+ if (kBuilding.getWarWearinessModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_WAR_WEAR_MOD", kBuilding.getWarWearinessModifier()));
+ }
+
+ if (kBuilding.getGlobalWarWearinessModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_WAR_WEAR_MOD_ALL_CITIES", kBuilding.getGlobalWarWearinessModifier()));
+ }
+
+ if (kBuilding.getEnemyWarWearinessModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_ENEMY_WAR_WEAR", kBuilding.getEnemyWarWearinessModifier()));
+ }
+
+ if (kBuilding.getHealRateChange() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_HEAL_MOD", kBuilding.getHealRateChange()));
+ }
+
+ if (kBuilding.getAreaHealth() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_HEALTH_CHANGE_CONT", abs(kBuilding.getAreaHealth()), ((kBuilding.getAreaHealth() > 0) ? gDLL->getSymbolID(HEALTHY_CHAR): gDLL->getSymbolID(UNHEALTHY_CHAR))));
+ }
+
+ if (kBuilding.getGlobalHealth() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_HEALTH_CHANGE_ALL_CITIES", abs(kBuilding.getGlobalHealth()), ((kBuilding.getGlobalHealth() > 0) ? gDLL->getSymbolID(HEALTHY_CHAR): gDLL->getSymbolID(UNHEALTHY_CHAR))));
+ }
+
+ if (kBuilding.getAreaHappiness() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_HAPPY_CHANGE_CONT", kBuilding.getAreaHappiness(), ((kBuilding.getAreaHappiness() > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR))));
+ }
+
+ if (kBuilding.getGlobalHappiness() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_HAPPY_CHANGE_ALL_CITIES", kBuilding.getGlobalHappiness(), ((kBuilding.getGlobalHappiness() > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR))));
+ }
+
+ if (kBuilding.getStateReligionHappiness() > 0)
+ {
+ if (kBuilding.getReligionType() != NO_RELIGION)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_RELIGION_HAPPINESS", kBuilding.getStateReligionHappiness(), ((kBuilding.getStateReligionHappiness() > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR)), GC.getReligionInfo((ReligionTypes)(kBuilding.getReligionType())).getChar()));
+ }
+ }
+
+ if (kBuilding.getWorkerSpeedModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_WORKER_MOD", kBuilding.getWorkerSpeedModifier()));
+ }
+
+ if (kBuilding.getMilitaryProductionModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_MILITARY_MOD", kBuilding.getMilitaryProductionModifier()));
+ }
+
+ if (kBuilding.getSpaceProductionModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_SPACESHIP_MOD", kBuilding.getSpaceProductionModifier()));
+ }
+
+ if (kBuilding.getGlobalSpaceProductionModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_SPACESHIP_MOD_ALL_CITIES", kBuilding.getGlobalSpaceProductionModifier()));
+ }
+
+ if (kBuilding.getTradeRoutes() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_TRADE_ROUTES", kBuilding.getTradeRoutes()));
+ }
+
+ if (kBuilding.getCoastalTradeRoutes() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_COASTAL_TRADE_ROUTES", kBuilding.getCoastalTradeRoutes()));
+ }
+
+ if (kBuilding.getGlobalTradeRoutes() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_TRADE_ROUTES_ALL_CITIES", kBuilding.getGlobalTradeRoutes()));
+ }
+
+ if (kBuilding.getTradeRouteModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_TRADE_ROUTE_MOD", kBuilding.getTradeRouteModifier()));
+ }
+
+ if (kBuilding.getForeignTradeRouteModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_FOREIGN_TRADE_ROUTE_MOD", kBuilding.getForeignTradeRouteModifier()));
+ }
+
+ if (kBuilding.getGlobalPopulationChange() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_GLOBAL_POP", kBuilding.getGlobalPopulationChange()));
+ }
+
+ if (kBuilding.getFreeTechs() != 0)
+ {
+ if (kBuilding.getFreeTechs() == 1)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_FREE_TECH"));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_FREE_TECHS", kBuilding.getFreeTechs()));
+ }
+ }
+
+ if (kBuilding.getDefenseModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_DEFENSE_MOD", kBuilding.getDefenseModifier()));
+ }
+
+ if (kBuilding.getBombardDefenseModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_BOMBARD_DEFENSE_MOD", -kBuilding.getBombardDefenseModifier()));
+ }
+
+ if (kBuilding.getAllCityDefenseModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_DEFENSE_MOD_ALL_CITIES", kBuilding.getAllCityDefenseModifier()));
+ }
+
+ if (kBuilding.getEspionageDefenseModifier() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_ESPIONAGE_DEFENSE_MOD", kBuilding.getEspionageDefenseModifier()));
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_EXPOSE_SPIES"));
+ }
+
+ setYieldChangeHelp(szBuffer, gDLL->getText("TXT_KEY_BUILDING_WATER_PLOTS").c_str(), L": ", L"", kBuilding.getSeaPlotYieldChangeArray());
+
+ setYieldChangeHelp(szBuffer, gDLL->getText("TXT_KEY_BUILDING_RIVER_PLOTS").c_str(), L": ", L"", kBuilding.getRiverPlotYieldChangeArray());
+
+ setYieldChangeHelp(szBuffer, gDLL->getText("TXT_KEY_BUILDING_WATER_PLOTS_ALL_CITIES").c_str(), L": ", L"", kBuilding.getGlobalSeaPlotYieldChangeArray());
+
+ setYieldChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_BUILDING_WITH_POWER").c_str(), kBuilding.getPowerYieldModifierArray(), true);
+
+ setYieldChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_BUILDING_ALL_CITIES_THIS_CONTINENT").c_str(), kBuilding.getAreaYieldModifierArray(), true);
+
+ setYieldChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_BUILDING_ALL_CITIES").c_str(), kBuilding.getGlobalYieldModifierArray(), true);
+
+ setCommerceChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_BUILDING_ALL_CITIES").c_str(), kBuilding.getGlobalCommerceModifierArray(), true);
+
+ setCommerceChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_BUILDING_PER_SPECIALIST_ALL_CITIES").c_str(), kBuilding.getSpecialistExtraCommerceArray());
+
+ if (ePlayer != NO_PLAYER && GET_PLAYER(ePlayer).getStateReligion() != NO_RELIGION)
+ {
+ szTempBuffer = gDLL->getText("TXT_KEY_BUILDING_FROM_ALL_REL_BUILDINGS", GC.getReligionInfo(GET_PLAYER(ePlayer).getStateReligion()).getChar());
+ }
+ else
+ {
+ szTempBuffer = gDLL->getText("TXT_KEY_BUILDING_STATE_REL_BUILDINGS");
+ }
+ setCommerceChangeHelp(szBuffer, L"", L"", szTempBuffer, kBuilding.getStateReligionCommerceArray());
+
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; ++iI)
+ {
+ if (kBuilding.getCommerceHappiness(iI) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_PER_LEVEL", ((kBuilding.getCommerceHappiness(iI) > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR)), (100 / kBuilding.getCommerceHappiness(iI)), GC.getCommerceInfo((CommerceTypes)iI).getChar()));
+ }
+
+ if (kBuilding.isCommerceFlexible(iI) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_ADJUST_COMM_RATE", GC.getCommerceInfo((CommerceTypes) iI).getChar()));
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumSpecialistInfos(); ++iI)
+ {
+ szFirstBuffer = gDLL->getText("TXT_KEY_BUILDING_FROM_IN_ALL_CITIES", GC.getSpecialistInfo((SpecialistTypes) iI).getTextKeyWide());
+ setYieldChangeHelp(szBuffer, L"", L"", szFirstBuffer, kBuilding.getSpecialistYieldChangeArray(iI));
+ }
+
+ for (iI = 0; iI < GC.getNumBonusInfos(); ++iI)
+ {
+ szFirstBuffer = gDLL->getText("TXT_KEY_BUILDING_WITH_BONUS", GC.getBonusInfo((BonusTypes) iI).getTextKeyWide());
+ setYieldChangeHelp(szBuffer, L"", L"", szFirstBuffer, kBuilding.getBonusYieldModifierArray(iI), true);
+ }
+
+ for (iI = 0; iI < GC.getNumReligionInfos(); ++iI)
+ {
+ if (kBuilding.getReligionChange(iI) > 0)
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_BUILDING_SPREADS_RELIGION", GC.getReligionInfo((ReligionTypes) iI).getChar()).c_str());
+ szBuffer.append(szTempBuffer);
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumSpecialistInfos(); ++iI)
+ {
+ if (kBuilding.getSpecialistCount(iI) > 0)
+ {
+ if (kBuilding.getSpecialistCount(iI) == 1)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_TURN_CITIZEN_INTO", GC.getSpecialistInfo((SpecialistTypes) iI).getTextKeyWide()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_TURN_CITIZENS_INTO", kBuilding.getSpecialistCount(iI), GC.getSpecialistInfo((SpecialistTypes) iI).getTextKeyWide()));
+ }
+ }
+
+ if (kBuilding.getFreeSpecialistCount(iI) > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_FREE_SPECIALIST", kBuilding.getFreeSpecialistCount(iI), GC.getSpecialistInfo((SpecialistTypes) iI).getTextKeyWide()));
+ }
+ }
+
+ iLast = 0;
+
+ for (iI = 0; iI < GC.getNumImprovementInfos(); ++iI)
+ {
+ if (kBuilding.getImprovementFreeSpecialist(iI) > 0)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_BUILDING_IMPROVEMENT_FREE_SPECIALISTS", kBuilding.getImprovementFreeSpecialist(iI)).GetCString() );
+ szTempBuffer.Format(L"%s", GC.getImprovementInfo((ImprovementTypes)iI).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", (kBuilding.getImprovementFreeSpecialist(iI) != iLast));
+ iLast = kBuilding.getImprovementFreeSpecialist(iI);
+ }
+ }
+
+ iLast = 0;
+
+ for (iI = 0; iI < GC.getNumBonusInfos(); ++iI)
+ {
+ if (kBuilding.getBonusHealthChanges(iI) != 0)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_BUILDING_HEALTH_HAPPINESS_CHANGE", abs(kBuilding.getBonusHealthChanges(iI)), ((kBuilding.getBonusHealthChanges(iI) > 0) ? gDLL->getSymbolID(HEALTHY_CHAR): gDLL->getSymbolID(UNHEALTHY_CHAR))).c_str());
+ szTempBuffer.Format(L"%s", GC.getBonusInfo((BonusTypes)iI).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", (kBuilding.getBonusHealthChanges(iI) != iLast));
+ iLast = kBuilding.getBonusHealthChanges(iI);
+ }
+ }
+
+ iLast = 0;
+
+ for (iI = 0; iI < GC.getNumCivicInfos(); ++iI)
+ {
+ int iChange = GC.getCivicInfo((CivicTypes)iI).getBuildingHealthChanges(kBuilding.getBuildingClassType());
+ if (0 != iChange)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_BUILDING_CIVIC_HEALTH_HAPPINESS_CHANGE", abs(iChange), ((iChange > 0) ? gDLL->getSymbolID(HEALTHY_CHAR): gDLL->getSymbolID(UNHEALTHY_CHAR))).c_str());
+ szTempBuffer.Format(L"%s", GC.getCivicInfo((CivicTypes)iI).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", (iChange != iLast));
+ iLast = iChange;
+ }
+ }
+
+ // AGDM addition:
+ iLast = 0;
+ for (iI = 0; iI < GC.getNumCivicInfos(); ++iI)
+ {
+ int iChange = GC.getCivicInfo((CivicTypes)iI).getBuildingFreeExperiences(kBuilding.getBuildingClassType());
+ if (0 != iChange)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_BUILDING_CIVIC_FREE_XP", iChange).c_str());
+ szTempBuffer.Format(L"%s", GC.getCivicInfo((CivicTypes)iI).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", (iChange != iLast));
+ iLast = iChange;
+ }
+ }
+
+ // AGDM addition:
+ iLast = 0;
+ for (iI = 0; iI < GC.getNumCivicInfos(); ++iI)
+ {
+ int iChange = GC.getCivicInfo((CivicTypes)iI).getBuildingMilitaryProductionModifiers(kBuilding.getBuildingClassType());
+ if (0 != iChange)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_BUILDING_CIVIC_MILITARY_PRODUCTION", iChange).c_str());
+ szTempBuffer.Format(L"%s", GC.getCivicInfo((CivicTypes)iI).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", (iChange != iLast));
+ iLast = iChange;
+ }
+ }
+
+ // AGDM addition:
+ for (int iJ = 0; iJ < GC.getNumSpecialistInfos(); ++iJ)
+ {
+ iLast = 0;
+ for (iI = 0; iI < GC.getNumCivicInfos(); ++iI)
+ {
+ int iChange = GC.getCivicInfo((CivicTypes)iI).getBuildingFreeSpecialistCounts(kBuilding.getBuildingClassType(), iJ);
+ if (0 != iChange)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_BUILDING_CIVIC_FREE_SPECIALIST", iChange, GC.getSpecialistInfo((SpecialistTypes)iJ).getTextKeyWide()).c_str() );
+ szTempBuffer.Format(L"%s", GC.getCivicInfo((CivicTypes)iI).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", (iChange != iLast));
+ iLast = iChange;
+ }
+ }
+ }
+
+ // AGDM addition:
+ for (iI = 0; iI < GC.getNumCivicInfos(); ++iI)
+ {
+ szTempBuffer.Format(L"%s%s", gDLL->getText("TXT_KEY_BUILDING_CIVIC_WITH").c_str(), GC.getCivicInfo((CivicTypes)iI).getDescription());
+ int* aiModifiers = GC.getCivicInfo((CivicTypes)iI).getBuildingCommerceModifierArray(kBuilding.getBuildingClassType());
+ setCommerceChangeHelp(szBuffer, L"", L"", szTempBuffer, aiModifiers, true, true);
+ }
+ // AGDM addition:
+ for (iI = 0; iI < GC.getNumCivicInfos(); ++iI)
+ {
+ szTempBuffer.Format(L"%s%s", gDLL->getText("TXT_KEY_BUILDING_CIVIC_WITH").c_str(), GC.getCivicInfo((CivicTypes)iI).getDescription());
+ int* aiModifiers = GC.getCivicInfo((CivicTypes)iI).getBuildingCommerceChangeArray(kBuilding.getBuildingClassType());
+ setCommerceChangeHelp(szBuffer, L"", L"", szTempBuffer, aiModifiers, false, true);
+ }
+ // AGDM addition:
+ for (iI = 0; iI < GC.getNumCivicInfos(); ++iI)
+ {
+ szTempBuffer.Format(L"%s%s", gDLL->getText("TXT_KEY_BUILDING_CIVIC_WITH").c_str(), GC.getCivicInfo((CivicTypes)iI).getDescription());
+ int* aiModifiers = GC.getCivicInfo((CivicTypes)iI).getBuildingYieldModifierArray(kBuilding.getBuildingClassType());
+ setYieldChangeHelp(szBuffer, L"", L"", szTempBuffer, aiModifiers, true, true);
+ }
+ // AGDM addition:
+ for (iI = 0; iI < GC.getNumCivicInfos(); ++iI)
+ {
+ szTempBuffer.Format(L"%s%s", gDLL->getText("TXT_KEY_BUILDING_CIVIC_WITH").c_str(), GC.getCivicInfo((CivicTypes)iI).getDescription());
+ int* aiModifiers = GC.getCivicInfo((CivicTypes)iI).getBuildingYieldChangeArray(kBuilding.getBuildingClassType());
+ setYieldChangeHelp(szBuffer, L"", L"", szTempBuffer, aiModifiers, false, true);
+ }
+
+ iLast = 0;
+
+ for (iI = 0; iI < GC.getNumBonusInfos(); ++iI)
+ {
+ if (kBuilding.getBonusHappinessChanges(iI) != 0)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_BUILDING_HEALTH_HAPPINESS_CHANGE", abs(kBuilding.getBonusHappinessChanges(iI)), ((kBuilding.getBonusHappinessChanges(iI) > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR))).c_str());
+ szTempBuffer.Format(L"%s", GC.getBonusInfo((BonusTypes)iI).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", (kBuilding.getBonusHappinessChanges(iI) != iLast));
+ iLast = kBuilding.getBonusHappinessChanges(iI);
+ }
+ }
+
+ iLast = 0;
+
+ for (iI = 0; iI < GC.getNumCivicInfos(); ++iI)
+ {
+ int iChange = GC.getCivicInfo((CivicTypes)iI).getBuildingHappinessChanges(kBuilding.getBuildingClassType());
+ if (0 != iChange)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_BUILDING_CIVIC_HEALTH_HAPPINESS_CHANGE", abs(iChange), ((iChange > 0) ? gDLL->getSymbolID(HAPPY_CHAR): gDLL->getSymbolID(UNHAPPY_CHAR))).c_str());
+ szTempBuffer.Format(L"%s", GC.getCivicInfo((CivicTypes)iI).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", (iChange != iLast));
+ iLast = iChange;
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); ++iI)
+ {
+ if (kBuilding.getUnitCombatFreeExperience(iI) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_FREE_XP", GC.getUnitCombatInfo((UnitCombatTypes)iI).getTextKeyWide(), kBuilding.getUnitCombatFreeExperience(iI)));
+ }
+ }
+
+ for (iI = 0; iI < NUM_DOMAIN_TYPES; ++iI)
+ {
+ if (kBuilding.getDomainFreeExperience(iI) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_FREE_XP", GC.getDomainInfo((DomainTypes)iI).getTextKeyWide(), kBuilding.getDomainFreeExperience(iI)));
+ }
+ }
+
+ for (iI = 0; iI < NUM_DOMAIN_TYPES; ++iI)
+ {
+ if (kBuilding.getDomainProductionModifier(iI) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_BUILDS_FASTER_DOMAIN", GC.getDomainInfo((DomainTypes)iI).getTextKeyWide(), kBuilding.getDomainProductionModifier(iI)));
+ }
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumUnitInfos(); ++iI)
+ {
+ if (GC.getUnitInfo((UnitTypes)iI).getPrereqBuilding() == eBuilding)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_BUILDING_REQUIRED_TO_TRAIN").c_str());
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_UNIT_TEXT"), GC.getUnitInfo((UnitTypes)iI).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumUnitInfos(); ++iI)
+ {
+ if (GC.getUnitInfo((UnitTypes)iI).getBuildings(eBuilding) || GC.getUnitInfo((UnitTypes)iI).getForceBuildings(eBuilding))
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_UNIT_REQUIRED_TO_BUILD").c_str());
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_UNIT_TEXT"), GC.getUnitInfo((UnitTypes)iI).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ iLast = 0;
+
+ for (iI = 0; iI < GC.getNumBuildingClassInfos(); ++iI)
+ {
+ if (kBuilding.getBuildingHappinessChanges(iI) != 0)
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_BUILDING_HAPPINESS_CHANGE", kBuilding.getBuildingHappinessChanges(iI),
+ ((kBuilding.getBuildingHappinessChanges(iI) > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR))).c_str());
+ CvWString szBuilding;
+ if (NO_PLAYER != ePlayer)
+ {
+ BuildingTypes ePlayerBuilding = ((BuildingTypes)(GC.getCivilizationInfo(GET_PLAYER(ePlayer).getCivilizationType()).getCivilizationBuildings(iI)));
+ if (NO_BUILDING != ePlayerBuilding)
+ {
+ szBuilding.Format(L"%s", GC.getBuildingClassInfo((BuildingClassTypes)iI).getDescription());
+ }
+ }
+ else
+ {
+ szBuilding.Format(L"%s", GC.getBuildingClassInfo((BuildingClassTypes)iI).getDescription());
+ }
+ setListHelp(szBuffer, szTempBuffer, szBuilding, L", ", (kBuilding.getBuildingHappinessChanges(iI) != iLast));
+ iLast = kBuilding.getBuildingHappinessChanges(iI);
+ }
+ }
+
+ if (kBuilding.getPowerBonus() != NO_BONUS)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_PROVIDES_POWER_WITH", GC.getBonusInfo((BonusTypes)kBuilding.getPowerBonus()).getTextKeyWide()));
+
+ if (kBuilding.isDirtyPower() && (GC.getDefineINT("DIRTY_POWER_HEALTH_CHANGE") != 0))
+ {
+ szTempBuffer.Format(L" (+%d%c)", abs(GC.getDefineINT("DIRTY_POWER_HEALTH_CHANGE")), ((GC.getDefineINT("DIRTY_POWER_HEALTH_CHANGE") > 0) ? gDLL->getSymbolID(HEALTHY_CHAR): gDLL->getSymbolID(UNHEALTHY_CHAR)));
+ szBuffer.append(szTempBuffer);
+ }
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumBuildingClassInfos(); ++iI)
+ {
+ if (ePlayer != NO_PLAYER)
+ {
+ eLoopBuilding = ((BuildingTypes)(GC.getCivilizationInfo(GET_PLAYER(ePlayer).getCivilizationType()).getCivilizationBuildings(iI)));
+ }
+ else
+ {
+ eLoopBuilding = (BuildingTypes)GC.getBuildingClassInfo((BuildingClassTypes)iI).getDefaultBuildingIndex();
+ }
+
+ if (eLoopBuilding != NO_BUILDING)
+ {
+ if (GC.getBuildingInfo(eLoopBuilding).isBuildingClassNeededInCity(kBuilding.getBuildingClassType()))
+ {
+ if ((pCity == NULL) || pCity->canConstruct(eLoopBuilding, false, true))
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_BUILDING_REQUIRED_TO_BUILD").c_str());
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR("COLOR_BUILDING_TEXT"), GC.getBuildingInfo(eLoopBuilding).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+ }
+ }
+
+ if (bCivilopediaText)
+ {
+ // Trait
+ for (int i = 0; i < GC.getNumTraitInfos(); ++i)
+ {
+ if (kBuilding.getProductionTraits((TraitTypes)i) != 0)
+ {
+ if (kBuilding.getProductionTraits((TraitTypes)i) == 100)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_DOUBLE_SPEED_TRAIT", GC.getTraitInfo((TraitTypes)i).getTextKeyWide()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PRODUCTION_MODIFIER_TRAIT", kBuilding.getProductionTraits((TraitTypes)i), GC.getTraitInfo((TraitTypes)i).getTextKeyWide()));
+ }
+ }
+ }
+
+ for (int i = 0; i < GC.getNumTraitInfos(); ++i)
+ {
+ if (kBuilding.getHappinessTraits((TraitTypes)i) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_HAPPINESS_TRAIT", kBuilding.getHappinessTraits((TraitTypes)i), GC.getTraitInfo((TraitTypes)i).getTextKeyWide()));
+ }
+ }
+ }
+
+ if (bCivilopediaText)
+ {
+ if (kBuilding.getGreatPeopleUnitClass() != NO_UNITCLASS)
+ {
+ if (ePlayer != NO_PLAYER)
+ {
+ eGreatPeopleUnit = ((UnitTypes)(GC.getCivilizationInfo(GET_PLAYER(ePlayer).getCivilizationType()).getCivilizationUnits(kBuilding.getGreatPeopleUnitClass())));
+ }
+ else
+ {
+ eGreatPeopleUnit = (UnitTypes)GC.getUnitClassInfo((UnitClassTypes)kBuilding.getGreatPeopleUnitClass()).getDefaultUnitIndex();
+ }
+
+ if (eGreatPeopleUnit!= NO_UNIT)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_LIKELY_TO_GENERATE", GC.getUnitInfo(eGreatPeopleUnit).getTextKeyWide()));
+ }
+ }
+
+ if (kBuilding.getFreeStartEra() != NO_ERA)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_FREE_START_ERA", GC.getEraInfo((EraTypes)kBuilding.getFreeStartEra()).getTextKeyWide()));
+ }
+ }
+
+ if (!CvWString(kBuilding.getHelp()).empty())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(kBuilding.getHelp());
+ }
+
+ buildBuildingRequiresString(szBuffer, eBuilding, bCivilopediaText, bTechChooserText, pCity);
+
+ if (pCity != NULL)
+ {
+ if (!(GC.getBuildingClassInfo((BuildingClassTypes)(kBuilding.getBuildingClassType())).isNoLimit()))
+ {
+ if (isWorldWonderClass((BuildingClassTypes)(kBuilding.getBuildingClassType())))
+ {
+ if (pCity->isWorldWondersMaxed())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_WORLD_WONDERS_PER_CITY", GC.getDefineINT("MAX_WORLD_WONDERS_PER_CITY")));
+ }
+ }
+ else if (isTeamWonderClass((BuildingClassTypes)(kBuilding.getBuildingClassType())))
+ {
+ if (pCity->isTeamWondersMaxed())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_TEAM_WONDERS_PER_CITY", GC.getDefineINT("MAX_TEAM_WONDERS_PER_CITY")));
+ }
+ }
+ else if (isNationalWonderClass((BuildingClassTypes)(kBuilding.getBuildingClassType())))
+ {
+ if (pCity->isNationalWondersMaxed())
+ {
+ int iMaxNumWonders = (GC.getGameINLINE().isOption(GAMEOPTION_ONE_CITY_CHALLENGE) && GET_PLAYER(pCity->getOwnerINLINE()).isHuman()) ? GC.getDefineINT("MAX_NATIONAL_WONDERS_PER_CITY_FOR_OCC") : GC.getDefineINT("MAX_NATIONAL_WONDERS_PER_CITY");
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_NATIONAL_WONDERS_PER_CITY", iMaxNumWonders));
+ }
+ }
+ else
+ {
+ if (pCity->isBuildingsMaxed())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_NUM_PER_CITY", GC.getDefineINT("MAX_BUILDINGS_PER_CITY")));
+ }
+ }
+ }
+ }
+
+ if ((pCity == NULL) || pCity->getNumRealBuilding(eBuilding) < GC.getCITY_MAX_NUM_BUILDINGS())
+ {
+ if (!bCivilopediaText)
+ {
+ if (pCity == NULL)
+ {
+ if (kBuilding.getProductionCost() > 0)
+ {
+ szTempBuffer.Format(L"\n%d%c", (ePlayer != NO_PLAYER ? GET_PLAYER(ePlayer).getProductionNeeded(eBuilding) : kBuilding.getProductionCost()), GC.getYieldInfo(YIELD_PRODUCTION).getChar());
+ szBuffer.append(szTempBuffer);
+ }
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_NUM_TURNS", pCity->getProductionTurnsLeft(eBuilding, ((gDLL->ctrlKey() || !(gDLL->shiftKey())) ? 0 : pCity->getOrderQueueLength()))));
+
+ iProduction = pCity->getBuildingProduction(eBuilding);
+
+ int iProductionNeeded = pCity->getProductionNeeded(eBuilding);
+ if (iProduction > 0)
+ {
+ szTempBuffer.Format(L" - %d/%d%c", iProduction, iProductionNeeded, GC.getYieldInfo(YIELD_PRODUCTION).getChar());
+ szBuffer.append(szTempBuffer);
+ }
+ else
+ {
+ szTempBuffer.Format(L" - %d%c", iProductionNeeded, GC.getYieldInfo(YIELD_PRODUCTION).getChar());
+ szBuffer.append(szTempBuffer);
+ }
+ }
+ }
+
+ for (int iI = 0; iI < GC.getNumBonusInfos(); ++iI)
+ {
+ if (kBuilding.getBonusProductionModifier(iI) != 0)
+ {
+ if (pCity != NULL)
+ {
+ if (pCity->hasBonus((BonusTypes)iI))
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_COLOR_POSITIVE"));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_COLOR_NEGATIVE"));
+ }
+ }
+ if (!bCivilopediaText)
+ {
+ szBuffer.append(L" (");
+ }
+ else
+ {
+ szTempBuffer.Format(L"\n%c", gDLL->getSymbolID(BULLET_CHAR), szTempBuffer);
+ szBuffer.append(szTempBuffer);
+ }
+ if (kBuilding.getBonusProductionModifier(iI) == 100)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_DOUBLE_SPEED_WITH", GC.getBonusInfo((BonusTypes)iI).getTextKeyWide()));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_BUILDS_FASTER_WITH", kBuilding.getBonusProductionModifier(iI), GC.getBonusInfo((BonusTypes)iI).getTextKeyWide()));
+ }
+ if (!bCivilopediaText)
+ {
+ szBuffer.append(L')');
+ }
+ if (pCity != NULL)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_COLOR_REVERT"));
+ }
+ }
+ }
+
+ if (kBuilding.getObsoleteTech() != NO_TECH)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_OBSOLETE_WITH", GC.getTechInfo((TechTypes) kBuilding.getObsoleteTech()).getTextKeyWide()));
+
+ if (kBuilding.getDefenseModifier() != 0 || kBuilding.getBombardDefenseModifier() != 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_OBSOLETE_EXCEPT"));
+ }
+ }
+
+ if (kBuilding.getSpecialBuildingType() != NO_SPECIALBUILDING)
+ {
+ if (GC.getSpecialBuildingInfo((SpecialBuildingTypes) kBuilding.getSpecialBuildingType()).getObsoleteTech() != NO_TECH)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_OBSOLETE_WITH", GC.getTechInfo((TechTypes) GC.getSpecialBuildingInfo((SpecialBuildingTypes) kBuilding.getSpecialBuildingType()).getObsoleteTech()).getTextKeyWide()));
+ }
+ }
+
+ if ((gDLL->getChtLvl() > 0) && gDLL->ctrlKey() && (pCity != NULL))
+ {
+ int iBuildingValue = pCity->AI_buildingValue(eBuilding);
+ szBuffer.append(CvWString::format(L"\nAI Building Value = %d", iBuildingValue));
+ }
+ }
+
+ if (bStrategyText)
+ {
+ if (!CvWString(kBuilding.getStrategy()).empty())
+ {
+ if ((ePlayer == NO_PLAYER) || GET_PLAYER(ePlayer).isOption(PLAYEROPTION_ADVISOR_HELP))
+ {
+ szBuffer.append(SEPARATOR);
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_SIDS_TIPS"));
+ szBuffer.append(L'\"');
+ szBuffer.append(kBuilding.getStrategy());
+ szBuffer.append(L'\"');
+ }
+ }
+ }
+
+ if (bCivilopediaText)
+ {
+ if (eDefaultBuilding == eBuilding)
+ {
+ for (iI = 0; iI < GC.getNumBuildingInfos(); ++iI)
+ {
+ if (iI != eBuilding)
+ {
+ if (eBuildingClass == GC.getBuildingInfo((BuildingTypes)iI).getBuildingClassType())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_REPLACED_BY_BUILDING", GC.getBuildingInfo((BuildingTypes)iI).getTextKeyWide()));
+ }
+ }
+ }
+ }
+ }
+
+}
+
+void CvGameTextMgr::buildBuildingRequiresString(CvWStringBuffer& szBuffer, BuildingTypes eBuilding, bool bCivilopediaText, bool bTechChooserText, const CvCity* pCity)
+{
+ bool bFirst;
+ PlayerTypes ePlayer;
+ CvWString szTempBuffer;
+ CvWString szFirstBuffer;
+ CvBuildingInfo& kBuilding = GC.getBuildingInfo(eBuilding);
+ BuildingTypes eLoopBuilding;
+
+ if (pCity != NULL)
+ {
+ ePlayer = pCity->getOwnerINLINE();
+ }
+ else
+ {
+ ePlayer = GC.getGameINLINE().getActivePlayer();
+ }
+
+ if (NULL == pCity || !pCity->canConstruct(eBuilding))
+ {
+ if (kBuilding.getHolyCity() != NO_RELIGION)
+ {
+ if (pCity == NULL || !pCity->isHolyCity((ReligionTypes)(kBuilding.getHolyCity())))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ACTION_ONLY_HOLY_CONSTRUCT", GC.getReligionInfo((ReligionTypes) kBuilding.getHolyCity()).getChar()));
+ }
+ }
+
+ bFirst = true;
+
+ if (kBuilding.getSpecialBuildingType() != NO_SPECIALBUILDING)
+ {
+ if ((pCity == NULL) || !(GC.getGameINLINE().isSpecialBuildingValid((SpecialBuildingTypes)(kBuilding.getSpecialBuildingType()))))
+ {
+ for (int iI = 0; iI < GC.getNumProjectInfos(); ++iI)
+ {
+ if (GC.getProjectInfo((ProjectTypes)iI).getEveryoneSpecialBuilding() == kBuilding.getSpecialBuildingType())
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_REQUIRES").c_str());
+ CvWString szProject;
+ szProject.Format(L"%s", GC.getProjectInfo((ProjectTypes)iI).getDescription());
+ setListHelp(szBuffer, szTempBuffer, szProject, gDLL->getText("TXT_KEY_OR").c_str(), bFirst);
+ bFirst = false;
+ }
+ }
+ }
+ }
+
+ if (!bFirst)
+ {
+ szBuffer.append(ENDCOLR);
+ }
+
+ if (kBuilding.getSpecialBuildingType() != NO_SPECIALBUILDING)
+ {
+ if ((pCity == NULL) || !(GC.getGameINLINE().isSpecialBuildingValid((SpecialBuildingTypes)(kBuilding.getSpecialBuildingType()))))
+ {
+ TechTypes eTech = (TechTypes)GC.getSpecialBuildingInfo((SpecialBuildingTypes)kBuilding.getSpecialBuildingType()).getTechPrereqAnyone();
+ if (NO_TECH != eTech)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_REQUIRES_TECH_ANYONE", GC.getTechInfo(eTech).getTextKeyWide()));
+ }
+ }
+ }
+
+ for (int iI = 0; iI < GC.getNumBuildingClassInfos(); ++iI)
+ {
+ if (ePlayer == NO_PLAYER && kBuilding.getPrereqNumOfBuildingClass((BuildingClassTypes)iI) > 0)
+ {
+ eLoopBuilding = (BuildingTypes)GC.getBuildingClassInfo((BuildingClassTypes)iI).getDefaultBuildingIndex();
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_BUILDING_REQUIRES_NUM_SPECIAL_BUILDINGS_NO_CITY", GC.getBuildingInfo(eLoopBuilding).getTextKeyWide(), kBuilding.getPrereqNumOfBuildingClass((BuildingClassTypes)iI)).c_str());
+
+ szBuffer.append(szTempBuffer);
+ }
+ else if (ePlayer != NO_PLAYER && GET_PLAYER(ePlayer).getBuildingClassPrereqBuilding(eBuilding, ((BuildingClassTypes)iI)) > 0)
+ {
+ if ((pCity == NULL) || (GET_PLAYER(ePlayer).getBuildingClassCount((BuildingClassTypes)iI) < GET_PLAYER(ePlayer).getBuildingClassPrereqBuilding(eBuilding, ((BuildingClassTypes)iI))))
+ {
+ eLoopBuilding = ((BuildingTypes)(GC.getCivilizationInfo(GET_PLAYER(ePlayer).getCivilizationType()).getCivilizationBuildings(iI)));
+
+ if (eLoopBuilding != NO_BUILDING)
+ {
+ if (pCity != NULL)
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_BUILDING_REQUIRES_NUM_SPECIAL_BUILDINGS", GC.getBuildingInfo(eLoopBuilding).getTextKeyWide(), GET_PLAYER(ePlayer).getBuildingClassCount((BuildingClassTypes)iI), GET_PLAYER(ePlayer).getBuildingClassPrereqBuilding(eBuilding, ((BuildingClassTypes)iI))).c_str());
+ }
+ else
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_BUILDING_REQUIRES_NUM_SPECIAL_BUILDINGS_NO_CITY", GC.getBuildingInfo(eLoopBuilding).getTextKeyWide(), GET_PLAYER(ePlayer).getBuildingClassPrereqBuilding(eBuilding, ((BuildingClassTypes)iI))).c_str());
+ }
+
+ szBuffer.append(szTempBuffer);
+ }
+ }
+ }
+ else if (kBuilding.isBuildingClassNeededInCity(iI))
+ {
+ if (NO_PLAYER != ePlayer)
+ {
+ eLoopBuilding = ((BuildingTypes)(GC.getCivilizationInfo(GET_PLAYER(ePlayer).getCivilizationType()).getCivilizationBuildings(iI)));
+ }
+ else
+ {
+ eLoopBuilding = (BuildingTypes)GC.getBuildingClassInfo((BuildingClassTypes)iI).getDefaultBuildingIndex();
+ }
+
+ if (eLoopBuilding != NO_BUILDING)
+ {
+ if ((pCity == NULL) || (pCity->getNumBuilding(eLoopBuilding) <= 0))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_REQUIRES_STRING", GC.getBuildingInfo(eLoopBuilding).getTextKeyWide()));
+ }
+ }
+ }
+ }
+
+ if (kBuilding.isStateReligion())
+ {
+ if (NULL == pCity || NO_PLAYER == ePlayer || NO_RELIGION == GET_PLAYER(ePlayer).getStateReligion() || !pCity->isHasReligion(GET_PLAYER(ePlayer).getStateReligion()))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_REQUIRES_STATE_RELIGION"));
+ }
+ }
+
+ if (kBuilding.getNumCitiesPrereq() > 0)
+ {
+ if (NO_PLAYER == ePlayer || GET_PLAYER(ePlayer).getNumCities() < kBuilding.getNumCitiesPrereq())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_REQUIRES_NUM_CITIES", kBuilding.getNumCitiesPrereq()));
+ }
+ }
+
+ if (kBuilding.getUnitLevelPrereq() > 0)
+ {
+ if (NO_PLAYER == ePlayer || GET_PLAYER(ePlayer).getHighestUnitLevel() < kBuilding.getUnitLevelPrereq())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_REQUIRES_UNIT_LEVEL", kBuilding.getUnitLevelPrereq()));
+ }
+ }
+
+ if (kBuilding.getMinLatitude() > 0)
+ {
+ if (NULL == pCity || pCity->plot()->getLatitude() < kBuilding.getMinLatitude())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_MIN_LATITUDE", kBuilding.getMinLatitude()));
+ }
+ }
+
+ if (kBuilding.getMaxLatitude() < 90)
+ {
+ if (NULL == pCity || pCity->plot()->getLatitude() > kBuilding.getMaxLatitude())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_MAX_LATITUDE", kBuilding.getMaxLatitude()));
+ }
+ }
+
+ if (pCity != NULL)
+ {
+ if (GC.getGameINLINE().isNoNukes())
+ {
+ if (kBuilding.isAllowsNukes())
+ {
+ for (int iI = 0; iI < GC.getNumUnitInfos(); ++iI)
+ {
+ if (GC.getUnitInfo((UnitTypes)iI).getNukeRange() != -1)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_NO_NUKES"));
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (bCivilopediaText)
+ {
+ if (kBuilding.getVictoryPrereq() != NO_VICTORY)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_REQUIRES_VICTORY", GC.getVictoryInfo((VictoryTypes)(kBuilding.getVictoryPrereq())).getTextKeyWide()));
+ }
+
+ if (kBuilding.getMaxStartEra() != NO_ERA)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_MAX_START_ERA", GC.getEraInfo((EraTypes)kBuilding.getMaxStartEra()).getTextKeyWide()));
+ }
+
+ if (kBuilding.getNumTeamsPrereq() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_REQUIRES_NUM_TEAMS", kBuilding.getNumTeamsPrereq()));
+ }
+ }
+ else
+ {
+ if (!bTechChooserText)
+ {
+ if (kBuilding.getPrereqAndTech() != NO_TECH)
+ {
+ if (ePlayer == NO_PLAYER || !(GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isHasTech((TechTypes)(kBuilding.getPrereqAndTech()))))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_REQUIRES_STRING", GC.getTechInfo((TechTypes)(kBuilding.getPrereqAndTech())).getTextKeyWide()));
+ }
+ }
+ }
+
+ bFirst = true;
+
+ for (int iI = 0; iI < GC.getNUM_BUILDING_AND_TECH_PREREQS(); ++iI)
+ {
+ if (kBuilding.getPrereqAndTechs(iI) != NO_TECH)
+ {
+ if (bTechChooserText || ePlayer == NO_PLAYER || !(GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isHasTech((TechTypes)(kBuilding.getPrereqAndTechs(iI)))))
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_REQUIRES").c_str());
+ setListHelp(szBuffer, szTempBuffer, GC.getTechInfo(((TechTypes)(kBuilding.getPrereqAndTechs(iI)))).getDescription(), gDLL->getText("TXT_KEY_AND").c_str(), bFirst);
+ bFirst = false;
+ }
+ }
+ }
+
+ if (!bFirst)
+ {
+ szBuffer.append(ENDCOLR);
+ }
+
+ if (kBuilding.getPrereqAndBonus() != NO_BONUS)
+ {
+ if ((pCity == NULL) || !(pCity->hasBonus((BonusTypes)kBuilding.getPrereqAndBonus())))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_REQUIRES_STRING", GC.getBonusInfo((BonusTypes)kBuilding.getPrereqAndBonus()).getTextKeyWide()));
+ }
+ }
+
+ CvWStringBuffer szBonusList;
+ bFirst = true;
+
+ for (int iI = 0; iI < GC.getNUM_BUILDING_PREREQ_OR_BONUSES(); ++iI)
+ {
+ if (kBuilding.getPrereqOrBonuses(iI) != NO_BONUS)
+ {
+ if ((pCity == NULL) || !(pCity->hasBonus((BonusTypes)kBuilding.getPrereqOrBonuses(iI))))
+ {
+ szTempBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_REQUIRES").c_str());
+ setListHelp(szBonusList, szTempBuffer, GC.getBonusInfo((BonusTypes)kBuilding.getPrereqOrBonuses(iI)).getDescription(), gDLL->getText("TXT_KEY_OR").c_str(), bFirst);
+ bFirst = false;
+ }
+ else if (NULL != pCity)
+ {
+ bFirst = true;
+ break;
+ }
+ }
+ }
+
+ if (!bFirst)
+ {
+ szBonusList.append(ENDCOLR);
+ szBuffer.append(szBonusList);
+ }
+
+ if (NO_CORPORATION != kBuilding.getFoundsCorporation())
+ {
+ bFirst = true;
+ szBonusList.clear();
+ for (int iI = 0; iI < GC.getNUM_CORPORATION_PREREQ_BONUSES(); ++iI)
+ {
+ BonusTypes eBonus = (BonusTypes)GC.getCorporationInfo((CorporationTypes)kBuilding.getFoundsCorporation()).getPrereqBonus(iI);
+ if (NO_BONUS != eBonus)
+ {
+ if ((pCity == NULL) || !(pCity->hasBonus(eBonus)))
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_REQUIRES").c_str());
+ szTempBuffer.Format(L"%s", GC.getBonusInfo(eBonus).getDescription());
+ setListHelp(szBonusList, szFirstBuffer, szTempBuffer, gDLL->getText("TXT_KEY_OR"), bFirst);
+ bFirst = false;
+ }
+ else if (NULL != pCity)
+ {
+ bFirst = true;
+ break;
+ }
+ }
+ }
+
+ if (!bFirst)
+ {
+ szBonusList.append(ENDCOLR);
+ szBuffer.append(szBonusList);
+ }
+ }
+ }
+ }
+}
+
+
+void CvGameTextMgr::setProjectHelp(CvWStringBuffer &szBuffer, ProjectTypes eProject, bool bCivilopediaText, CvCity* pCity)
+{
+ PROFILE_FUNC();
+
+ CvWString szTempBuffer;
+ CvWString szFirstBuffer;
+ PlayerTypes ePlayer;
+ bool bFirst;
+ int iProduction;
+ int iI;
+
+ if (NO_PROJECT == eProject)
+ {
+ return;
+ }
+
+ CvProjectInfo& kProject = GC.getProjectInfo(eProject);
+
+ if (pCity != NULL)
+ {
+ ePlayer = pCity->getOwnerINLINE();
+ }
+ else
+ {
+ ePlayer = GC.getGameINLINE().getActivePlayer();
+ }
+
+ if (!bCivilopediaText)
+ {
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_PROJECT_TEXT"), kProject.getDescription());
+ szBuffer.append(szTempBuffer);
+
+ if (isWorldProject(eProject))
+ {
+ if (pCity == NULL)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_WORLD_NUM_ALLOWED", kProject.getMaxGlobalInstances()));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_WORLD_NUM_LEFT", (kProject.getMaxGlobalInstances() - GC.getGameINLINE().getProjectCreatedCount(eProject) - GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getProjectMaking(eProject))));
+ }
+ }
+
+ if (isTeamProject(eProject))
+ {
+ if (pCity == NULL)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_TEAM_NUM_ALLOWED", kProject.getMaxTeamInstances()));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_TEAM_NUM_LEFT", (kProject.getMaxTeamInstances() - GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getProjectCount(eProject) - GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getProjectMaking(eProject))));
+ }
+ }
+ }
+
+ if (kProject.getNukeInterception() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_CHANCE_INTERCEPT_NUKES", kProject.getNukeInterception()));
+ }
+
+ if (kProject.getTechShare() != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_TECH_SHARE", kProject.getTechShare()));
+ }
+
+ if (kProject.isAllowsNukes())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_ENABLES_NUKES"));
+ }
+
+ if (kProject.getEveryoneSpecialUnit() != NO_SPECIALUNIT)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_ENABLES_SPECIAL", GC.getSpecialUnitInfo((SpecialUnitTypes)(kProject.getEveryoneSpecialUnit())).getTextKeyWide()));
+ }
+
+ if (kProject.getEveryoneSpecialBuilding() != NO_SPECIALBUILDING)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_ENABLES_SPECIAL", GC.getSpecialBuildingInfo((SpecialBuildingTypes)(kProject.getEveryoneSpecialBuilding())).getTextKeyWide()));
+ }
+
+ for (iI = 0; iI < GC.getNumVictoryInfos(); ++iI)
+ {
+ if (kProject.getVictoryThreshold(iI) > 0)
+ {
+ if (kProject.getVictoryThreshold(iI) == kProject.getVictoryMinThreshold(iI))
+ {
+ szTempBuffer.Format(L"%d", kProject.getVictoryThreshold(iI));
+ }
+ else
+ {
+ szTempBuffer.Format(L"%d-%d", kProject.getVictoryMinThreshold(iI), kProject.getVictoryThreshold(iI));
+ }
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_REQUIRED_FOR_VICTORY", szTempBuffer.GetCString(), GC.getVictoryInfo((VictoryTypes)iI).getTextKeyWide()));
+ }
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumProjectInfos(); ++iI)
+ {
+ if (GC.getProjectInfo((ProjectTypes)iI).getAnyoneProjectPrereq() == eProject)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_PROJECT_REQUIRED_TO_CREATE_ANYONE").c_str());
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR("COLOR_PROJECT_TEXT"), GC.getProjectInfo((ProjectTypes)iI).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ bFirst = true;
+
+ for (iI = 0; iI < GC.getNumProjectInfos(); ++iI)
+ {
+ if (GC.getProjectInfo((ProjectTypes)iI).getProjectsNeeded(eProject) > 0)
+ {
+ if ((pCity == NULL) || pCity->canCreate(((ProjectTypes)iI), false, true))
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_PROJECT_REQUIRED_TO_CREATE").c_str());
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR("COLOR_PROJECT_TEXT"), GC.getProjectInfo((ProjectTypes)iI).getDescription());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+ }
+
+ if ((pCity == NULL) || !(pCity->canCreate(eProject)))
+ {
+ if (pCity != NULL)
+ {
+ if (GC.getGameINLINE().isNoNukes())
+ {
+ if (kProject.isAllowsNukes())
+ {
+ for (iI = 0; iI < GC.getNumUnitInfos(); ++iI)
+ {
+ if (GC.getUnitInfo((UnitTypes)iI).getNukeRange() != -1)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_NO_NUKES"));
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (kProject.getAnyoneProjectPrereq() != NO_PROJECT)
+ {
+ if ((pCity == NULL) || (GC.getGameINLINE().getProjectCreatedCount((ProjectTypes)(kProject.getAnyoneProjectPrereq())) == 0))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_REQUIRES_ANYONE", GC.getProjectInfo((ProjectTypes)kProject.getAnyoneProjectPrereq()).getTextKeyWide()));
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumProjectInfos(); ++iI)
+ {
+ if (kProject.getProjectsNeeded(iI) > 0)
+ {
+ if ((pCity == NULL) || (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getProjectCount((ProjectTypes)iI) < kProject.getProjectsNeeded(iI)))
+ {
+ if (pCity != NULL)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_REQUIRES", GC.getProjectInfo((ProjectTypes)iI).getTextKeyWide(), GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getProjectCount((ProjectTypes)iI), kProject.getProjectsNeeded(iI)));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_REQUIRES_NO_CITY", GC.getProjectInfo((ProjectTypes)iI).getTextKeyWide(), kProject.getProjectsNeeded(iI)));
+ }
+ }
+ }
+ }
+
+ if (bCivilopediaText)
+ {
+ if (kProject.getVictoryPrereq() != NO_VICTORY)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_REQUIRES_STRING_VICTORY", GC.getVictoryInfo((VictoryTypes)(kProject.getVictoryPrereq())).getTextKeyWide()));
+ }
+ }
+ }
+
+ if (!bCivilopediaText)
+ {
+ if (pCity == NULL)
+ {
+ if (ePlayer != NO_PLAYER)
+ {
+ szTempBuffer.Format(L"\n%d%c", GET_PLAYER(ePlayer).getProductionNeeded(eProject), GC.getYieldInfo(YIELD_PRODUCTION).getChar());
+ }
+ else
+ {
+ szTempBuffer.Format(L"\n%d%c", kProject.getProductionCost(), GC.getYieldInfo(YIELD_PRODUCTION).getChar());
+ }
+ szBuffer.append(szTempBuffer);
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_NUM_TURNS", pCity->getProductionTurnsLeft(eProject, ((gDLL->ctrlKey() || !(gDLL->shiftKey())) ? 0 : pCity->getOrderQueueLength()))));
+
+ iProduction = pCity->getProjectProduction(eProject);
+
+ if (iProduction > 0)
+ {
+ szTempBuffer.Format(L" - %d/%d%c", iProduction, pCity->getProductionNeeded(eProject), GC.getYieldInfo(YIELD_PRODUCTION).getChar());
+ }
+ else
+ {
+ szTempBuffer.Format(L" - %d%c", pCity->getProductionNeeded(eProject), GC.getYieldInfo(YIELD_PRODUCTION).getChar());
+ }
+ szBuffer.append(szTempBuffer);
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumBonusInfos(); ++iI)
+ {
+ if (kProject.getBonusProductionModifier(iI) != 0)
+ {
+ if (pCity != NULL)
+ {
+ if (pCity->hasBonus((BonusTypes)iI))
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_COLOR_POSITIVE"));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_COLOR_NEGATIVE"));
+ }
+ }
+ if (!bCivilopediaText)
+ {
+ szBuffer.append(L" (");
+ }
+ else
+ {
+ szTempBuffer.Format(L"%s%c", NEWLINE, gDLL->getSymbolID(BULLET_CHAR), szTempBuffer);
+ szBuffer.append(szTempBuffer);
+ }
+ if (kProject.getBonusProductionModifier(iI) == 100)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_DOUBLE_SPEED_WITH", GC.getBonusInfo((BonusTypes)iI).getTextKeyWide()));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_PROJECT_BUILDS_FASTER_WITH", kProject.getBonusProductionModifier(iI), GC.getBonusInfo((BonusTypes)iI).getTextKeyWide()));
+ }
+ if (!bCivilopediaText)
+ {
+ szBuffer.append(L')');
+ }
+ if (pCity != NULL)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_COLOR_REVERT"));
+ }
+ }
+ }
+}
+
+
+void CvGameTextMgr::setProcessHelp(CvWStringBuffer &szBuffer, ProcessTypes eProcess)
+{
+ int iI;
+
+ szBuffer.append(GC.getProcessInfo(eProcess).getDescription());
+
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; ++iI)
+ {
+ if (GC.getProcessInfo(eProcess).getProductionToCommerceModifier(iI) != 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_PROCESS_CONVERTS", GC.getProcessInfo(eProcess).getProductionToCommerceModifier(iI), GC.getYieldInfo(YIELD_PRODUCTION).getChar(), GC.getCommerceInfo((CommerceTypes) iI).getChar()));
+ }
+ }
+}
+
+void CvGameTextMgr::setBadHealthHelp(CvWStringBuffer &szBuffer, CvCity& city)
+{
+ CvPlot* pLoopPlot;
+ FeatureTypes eFeature;
+ int iHealth;
+ int iI;
+
+ if (city.badHealth() > 0)
+ {
+ iHealth = -(city.getFreshWaterBadHealth());
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_FROM_FRESH_WATER", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = -(city.getFeatureBadHealth());
+ if (iHealth > 0)
+ {
+ eFeature = NO_FEATURE;
+
+ for (iI = 0; iI < NUM_CITY_PLOTS; ++iI)
+ {
+ pLoopPlot = plotCity(city.getX_INLINE(), city.getY_INLINE(), iI);
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->getFeatureType() != NO_FEATURE)
+ {
+ if (GC.getFeatureInfo(pLoopPlot->getFeatureType()).getHealthPercent() < 0)
+ {
+ if (eFeature == NO_FEATURE)
+ {
+ eFeature = pLoopPlot->getFeatureType();
+ }
+ else if (eFeature != pLoopPlot->getFeatureType())
+ {
+ eFeature = NO_FEATURE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_FEAT_HEALTH", iHealth, ((eFeature == NO_FEATURE) ? L"TXT_KEY_MISC_FEATURES" : GC.getFeatureInfo(eFeature).getTextKeyWide())));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = city.getEspionageHealthCounter();
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HEALTH_FROM_ESPIONAGE", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = -(city.getPowerBadHealth());
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HEALTH_FROM_POWER", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = -(city.getBonusBadHealth());
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HEALTH_FROM_BONUSES", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = -(city.totalBadBuildingHealth());
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HEALTH_FROM_BUILDINGS", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = -(GET_PLAYER(city.getOwnerINLINE()).getExtraHealth());
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HEALTH_FROM_CIV", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = -city.getExtraHealth();
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_UNHEALTH_EXTRA", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = -(GC.getHandicapInfo(city.getHandicapType()).getHealthBonus());
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HEALTH_FROM_HANDICAP", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = city.unhealthyPopulation();
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HEALTH_FROM_POP", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ szBuffer.append(L"-----------------------\n");
+
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_TOTAL_UNHEALTHY", city.badHealth()));
+ }
+}
+
+void CvGameTextMgr::setGoodHealthHelp(CvWStringBuffer &szBuffer, CvCity& city)
+{
+ CvPlot* pLoopPlot;
+ FeatureTypes eFeature;
+ int iHealth;
+ int iI;
+
+ if (city.goodHealth() > 0)
+ {
+ iHealth = city.getFreshWaterGoodHealth();
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HEALTH_FROM_FRESH_WATER", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = city.getFeatureGoodHealth();
+ if (iHealth > 0)
+ {
+ eFeature = NO_FEATURE;
+
+ for (iI = 0; iI < NUM_CITY_PLOTS; ++iI)
+ {
+ pLoopPlot = plotCity(city.getX_INLINE(), city.getY_INLINE(), iI);
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->getFeatureType() != NO_FEATURE)
+ {
+ if (GC.getFeatureInfo(pLoopPlot->getFeatureType()).getHealthPercent() > 0)
+ {
+ if (eFeature == NO_FEATURE)
+ {
+ eFeature = pLoopPlot->getFeatureType();
+ }
+ else if (eFeature != pLoopPlot->getFeatureType())
+ {
+ eFeature = NO_FEATURE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_FEAT_GOOD_HEALTH", iHealth, ((eFeature == NO_FEATURE) ? L"TXT_KEY_MISC_FEATURES" : GC.getFeatureInfo(eFeature).getTextKeyWide())));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = city.getPowerGoodHealth();
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_GOOD_HEALTH_FROM_POWER", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = city.getBonusGoodHealth();
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_GOOD_HEALTH_FROM_BONUSES", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = city.totalGoodBuildingHealth();
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_GOOD_HEALTH_FROM_BUILDINGS", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = GET_PLAYER(city.getOwnerINLINE()).getExtraHealth();
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_GOOD_HEALTH_FROM_CIV", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = city.getExtraHealth();
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HEALTH_EXTRA", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHealth = GC.getHandicapInfo(city.getHandicapType()).getHealthBonus();
+ if (iHealth > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_GOOD_HEALTH_FROM_HANDICAP", iHealth));
+ szBuffer.append(NEWLINE);
+ }
+
+ szBuffer.append(L"-----------------------\n");
+
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_TOTAL_HEALTHY", city.goodHealth()));
+ }
+}
+
+void CvGameTextMgr::setAngerHelp(CvWStringBuffer &szBuffer, CvCity& city)
+{
+ int iOldAngerPercent;
+ int iNewAngerPercent;
+ int iOldAnger;
+ int iNewAnger;
+ int iAnger;
+ int iI;
+
+ if (city.isOccupation())
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_RESISTANCE"));
+ }
+ else if (GET_PLAYER(city.getOwnerINLINE()).isAnarchy())
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_ANARCHY"));
+ }
+ else if (city.unhappyLevel() > 0)
+ {
+ iOldAngerPercent = 0;
+ iNewAngerPercent = 0;
+
+ iOldAnger = 0;
+ iNewAnger = 0;
+
+ // XXX decomp these???
+ iNewAngerPercent += city.getOvercrowdingPercentAnger();
+ iNewAnger += (((iNewAngerPercent * city.getPopulation()) / GC.getPERCENT_ANGER_DIVISOR()) - ((iOldAngerPercent * city.getPopulation()) / GC.getDefineINT("PERCENT_ANGER_DIVISOR")));
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_OVERCROWDING", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAngerPercent = iNewAngerPercent;
+ iOldAnger = iNewAnger;
+
+ iNewAngerPercent += city.getNoMilitaryPercentAnger();
+ iNewAnger += (((iNewAngerPercent * city.getPopulation()) / GC.getPERCENT_ANGER_DIVISOR()) - ((iOldAngerPercent * city.getPopulation()) / GC.getDefineINT("PERCENT_ANGER_DIVISOR")));
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_MILITARY_PROTECTION", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAngerPercent = iNewAngerPercent;
+ iOldAnger = iNewAnger;
+
+ iNewAngerPercent += city.getCulturePercentAnger();
+ iNewAnger += (((iNewAngerPercent * city.getPopulation()) / GC.getPERCENT_ANGER_DIVISOR()) - ((iOldAngerPercent * city.getPopulation()) / GC.getDefineINT("PERCENT_ANGER_DIVISOR")));
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_OCCUPIED", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAngerPercent = iNewAngerPercent;
+ iOldAnger = iNewAnger;
+
+ iNewAngerPercent += city.getReligionPercentAnger();
+ iNewAnger += (((iNewAngerPercent * city.getPopulation()) / GC.getPERCENT_ANGER_DIVISOR()) - ((iOldAngerPercent * city.getPopulation()) / GC.getDefineINT("PERCENT_ANGER_DIVISOR")));
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_RELIGION_FIGHT", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAngerPercent = iNewAngerPercent;
+ iOldAnger = iNewAnger;
+
+ iNewAngerPercent += city.getHurryPercentAnger();
+ iNewAnger += (((iNewAngerPercent * city.getPopulation()) / GC.getPERCENT_ANGER_DIVISOR()) - ((iOldAngerPercent * city.getPopulation()) / GC.getDefineINT("PERCENT_ANGER_DIVISOR")));
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_OPPRESSION", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAngerPercent = iNewAngerPercent;
+ iOldAnger = iNewAnger;
+
+ iNewAngerPercent += city.getConscriptPercentAnger();
+ iNewAnger += (((iNewAngerPercent * city.getPopulation()) / GC.getPERCENT_ANGER_DIVISOR()) - ((iOldAngerPercent * city.getPopulation()) / GC.getDefineINT("PERCENT_ANGER_DIVISOR")));
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_DRAFT", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAngerPercent = iNewAngerPercent;
+ iOldAnger = iNewAnger;
+
+ iNewAngerPercent += city.getDefyResolutionPercentAnger();
+ iNewAnger += (((iNewAngerPercent * city.getPopulation()) / GC.getPERCENT_ANGER_DIVISOR()) - ((iOldAngerPercent * city.getPopulation()) / GC.getDefineINT("PERCENT_ANGER_DIVISOR")));
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_DEFY_RESOLUTION", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAngerPercent = iNewAngerPercent;
+ iOldAnger = iNewAnger;
+
+ iNewAngerPercent += city.getWarWearinessPercentAnger();
+ iNewAnger += (((iNewAngerPercent * city.getPopulation()) / GC.getPERCENT_ANGER_DIVISOR()) - ((iOldAngerPercent * city.getPopulation()) / GC.getDefineINT("PERCENT_ANGER_DIVISOR")));
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_WAR_WEAR", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAngerPercent = iNewAngerPercent;
+ iOldAnger = iNewAnger;
+
+ iNewAnger += std::max(0, city.getVassalUnhappiness());
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_UNHAPPY_VASSAL", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAnger = iNewAnger;
+
+ iNewAnger += std::max(0, city.getEspionageHappinessCounter());
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_ESPIONAGE", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAnger = iNewAnger;
+
+ for (iI = 0; iI < GC.getNumCivicInfos(); ++iI)
+ {
+ iNewAngerPercent += GET_PLAYER(city.getOwnerINLINE()).getCivicPercentAnger((CivicTypes)iI);
+ iNewAnger += (((iNewAngerPercent * city.getPopulation()) / GC.getPERCENT_ANGER_DIVISOR()) - ((iOldAngerPercent * city.getPopulation()) / GC.getDefineINT("PERCENT_ANGER_DIVISOR")));
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_DEMAND_CIVIC", iAnger, GC.getCivicInfo((CivicTypes) iI).getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAngerPercent = iNewAngerPercent;
+ iOldAnger = iNewAnger;
+ }
+
+ iNewAnger -= std::min(0, city.getLargestCityHappiness());
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_BIG_CITY", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAnger = iNewAnger;
+
+ iNewAnger -= std::min(0, city.getMilitaryHappiness());
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_MILITARY_PRESENCE", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAnger = iNewAnger;
+
+ iNewAnger -= std::min(0, city.getCurrentStateReligionHappiness());
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_STATE_RELIGION", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAnger = iNewAnger;
+
+ iNewAnger -= std::min(0, (city.getBuildingBadHappiness() + city.getExtraBuildingBadHappiness()));
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_BUILDINGS", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAnger = iNewAnger;
+
+ iNewAnger -= std::min(0, city.getFeatureBadHappiness());
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_FEATURES", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAnger = iNewAnger;
+
+ iNewAnger -= std::min(0, city.getBonusBadHappiness());
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_BONUS", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAnger = iNewAnger;
+
+ iNewAnger -= std::min(0, city.getReligionBadHappiness());
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_RELIGIOUS_FREEDOM", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAnger = iNewAnger;
+
+ iNewAnger -= std::min(0, city.getCommerceHappiness());
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_BAD_ENTERTAINMENT", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAnger = iNewAnger;
+
+ iNewAnger -= std::min(0, city.area()->getBuildingHappiness(city.getOwnerINLINE()));
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_BUILDINGS", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAnger = iNewAnger;
+
+ iNewAnger -= std::min(0, GET_PLAYER(city.getOwnerINLINE()).getBuildingHappiness());
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_BUILDINGS", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAnger = iNewAnger;
+
+ iNewAnger -= std::min(0, (city.getExtraHappiness() + GET_PLAYER(city.getOwnerINLINE()).getExtraHappiness()));
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_ARGH", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAnger = iNewAnger;
+
+ iNewAnger -= std::min(0, GC.getHandicapInfo(city.getHandicapType()).getHappyBonus());
+ iAnger = ((iNewAnger - iOldAnger) + std::min(0, iOldAnger));
+ if (iAnger > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_HANDICAP", iAnger));
+ szBuffer.append(NEWLINE);
+ }
+ iOldAnger = iNewAnger;
+
+ szBuffer.append(L"-----------------------\n");
+
+ szBuffer.append(gDLL->getText("TXT_KEY_ANGER_TOTAL_UNHAPPY", iOldAnger));
+
+ FAssert(iOldAnger == city.unhappyLevel());
+ }
+}
+
+
+void CvGameTextMgr::setHappyHelp(CvWStringBuffer &szBuffer, CvCity& city)
+{
+ int iHappy;
+ int iTotalHappy = 0;
+
+ if (city.isOccupation() || GET_PLAYER(city.getOwnerINLINE()).isAnarchy())
+ {
+ return;
+ }
+ if (city.happyLevel() > 0)
+ {
+ iHappy = city.getLargestCityHappiness();
+ if (iHappy > 0)
+ {
+ iTotalHappy += iHappy;
+ szBuffer.append(gDLL->getText("TXT_KEY_HAPPY_BIG_CITY", iHappy));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHappy = city.getMilitaryHappiness();
+ if (iHappy > 0)
+ {
+ iTotalHappy += iHappy;
+ szBuffer.append(gDLL->getText("TXT_KEY_HAPPY_MILITARY_PRESENCE", iHappy));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHappy = city.getVassalHappiness();
+ if (iHappy > 0)
+ {
+ iTotalHappy += iHappy;
+ szBuffer.append(gDLL->getText("TXT_KEY_HAPPY_VASSAL", iHappy));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHappy = city.getCurrentStateReligionHappiness();
+ if (iHappy > 0)
+ {
+ iTotalHappy += iHappy;
+ szBuffer.append(gDLL->getText("TXT_KEY_HAPPY_STATE_RELIGION", iHappy));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHappy = (city.getBuildingGoodHappiness() + city.getExtraBuildingGoodHappiness());
+ if (iHappy > 0)
+ {
+ iTotalHappy += iHappy;
+ szBuffer.append(gDLL->getText("TXT_KEY_HAPPY_BUILDINGS", iHappy));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHappy = city.getFeatureGoodHappiness();
+ if (iHappy > 0)
+ {
+ iTotalHappy += iHappy;
+ szBuffer.append(gDLL->getText("TXT_KEY_HAPPY_FEATURES", iHappy));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHappy = city.getBonusGoodHappiness();
+ if (iHappy > 0)
+ {
+ iTotalHappy += iHappy;
+ szBuffer.append(gDLL->getText("TXT_KEY_HAPPY_BONUS", iHappy));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHappy = city.getReligionGoodHappiness();
+ if (iHappy > 0)
+ {
+ iTotalHappy += iHappy;
+ szBuffer.append(gDLL->getText("TXT_KEY_HAPPY_RELIGIOUS_FREEDOM", iHappy));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHappy = city.getCommerceHappiness();
+ if (iHappy > 0)
+ {
+ iTotalHappy += iHappy;
+ szBuffer.append(gDLL->getText("TXT_KEY_HAPPY_ENTERTAINMENT", iHappy));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHappy = city.area()->getBuildingHappiness(city.getOwnerINLINE());
+ if (iHappy > 0)
+ {
+ iTotalHappy += iHappy;
+ szBuffer.append(gDLL->getText("TXT_KEY_HAPPY_BUILDINGS", iHappy));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHappy = GET_PLAYER(city.getOwnerINLINE()).getBuildingHappiness();
+ if (iHappy > 0)
+ {
+ iTotalHappy += iHappy;
+ szBuffer.append(gDLL->getText("TXT_KEY_HAPPY_BUILDINGS", iHappy));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHappy = (city.getExtraHappiness() + GET_PLAYER(city.getOwnerINLINE()).getExtraHappiness());
+ if (iHappy > 0)
+ {
+ iTotalHappy += iHappy;
+ szBuffer.append(gDLL->getText("TXT_KEY_HAPPY_YEAH", iHappy));
+ szBuffer.append(NEWLINE);
+ }
+
+ if (city.getHappinessTimer() > 0)
+ {
+ iHappy = GC.getDefineINT("TEMP_HAPPY");
+ iTotalHappy += iHappy;
+ szBuffer.append(gDLL->getText("TXT_KEY_HAPPY_TEMP", iHappy, city.getHappinessTimer()));
+ szBuffer.append(NEWLINE);
+ }
+
+ iHappy = GC.getHandicapInfo(city.getHandicapType()).getHappyBonus();
+ if (iHappy > 0)
+ {
+ iTotalHappy += iHappy;
+ szBuffer.append(gDLL->getText("TXT_KEY_HAPPY_HANDICAP", iHappy));
+ szBuffer.append(NEWLINE);
+ }
+
+ szBuffer.append(L"-----------------------\n");
+
+ szBuffer.append(gDLL->getText("TXT_KEY_HAPPY_TOTAL_HAPPY", iTotalHappy));
+
+ FAssert(iTotalHappy == city.happyLevel())
+ }
+}
+
+void CvGameTextMgr::setYieldChangeHelp(CvWStringBuffer &szBuffer, const CvWString& szStart, const CvWString& szSpace, const CvWString& szEnd, const int* piYieldChange, bool bPercent, bool bNewLine)
+{
+ CvWString szTempBuffer;
+ bool bStarted;
+ int iI;
+
+ bStarted = false;
+
+ for (iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ if (piYieldChange[iI] != 0)
+ {
+ if (!bStarted)
+ {
+ if (bNewLine)
+ {
+ szTempBuffer.Format(L"\n%c", gDLL->getSymbolID(BULLET_CHAR));
+ }
+ szTempBuffer += CvWString::format(L"%s%s%s%d%s%c",
+ szStart.GetCString(),
+ szSpace.GetCString(),
+ piYieldChange[iI] > 0 ? L"+" : L"",
+ piYieldChange[iI],
+ bPercent ? L"%" : L"",
+ GC.getYieldInfo((YieldTypes)iI).getChar());
+ }
+ else
+ {
+ szTempBuffer.Format(L", %s%d%s%c",
+ piYieldChange[iI] > 0 ? L"+" : L"",
+ piYieldChange[iI],
+ bPercent ? L"%" : L"",
+ GC.getYieldInfo((YieldTypes)iI).getChar());
+ }
+ szBuffer.append(szTempBuffer);
+
+ bStarted = true;
+ }
+ }
+
+ if (bStarted)
+ {
+ szBuffer.append(szEnd);
+ }
+}
+
+void CvGameTextMgr::setCommerceChangeHelp(CvWStringBuffer &szBuffer, const CvWString& szStart, const CvWString& szSpace, const CvWString& szEnd, const int* piCommerceChange, bool bPercent, bool bNewLine)
+{
+ CvWString szTempBuffer;
+ bool bStarted;
+ int iI;
+
+ bStarted = false;
+
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; ++iI)
+ {
+ if (piCommerceChange[iI] != 0)
+ {
+ if (!bStarted)
+ {
+ if (bNewLine)
+ {
+ szTempBuffer.Format(L"\n%c", gDLL->getSymbolID(BULLET_CHAR));
+ }
+ szTempBuffer += CvWString::format(L"%s%s%s%d%s%c", szStart.GetCString(), szSpace.GetCString(), ((piCommerceChange[iI] > 0) ? L"+" : L""), piCommerceChange[iI], ((bPercent) ? L"%" : L""), GC.getCommerceInfo((CommerceTypes) iI).getChar());
+ }
+ else
+ {
+ szTempBuffer.Format(L", %s%d%s%c", ((piCommerceChange[iI] > 0) ? L"+" : L""), piCommerceChange[iI], ((bPercent) ? L"%" : L""), GC.getCommerceInfo((CommerceTypes) iI).getChar());
+ }
+ szBuffer.append(szTempBuffer);
+
+ bStarted = true;
+ }
+ }
+
+ if (bStarted)
+ {
+ szBuffer.append(szEnd);
+ }
+}
+
+void CvGameTextMgr::setBonusHelp(CvWStringBuffer &szBuffer, BonusTypes eBonus, bool bCivilopediaText)
+{
+ if (NO_BONUS == eBonus)
+ {
+ return;
+ }
+
+ if (!bCivilopediaText)
+ {
+ szBuffer.append(CvWString::format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), GC.getBonusInfo(eBonus).getDescription()));
+
+ if (NO_PLAYER != GC.getGameINLINE().getActivePlayer())
+ {
+ CvPlayer& kActivePlayer = GET_PLAYER(GC.getGameINLINE().getActivePlayer());
+ szBuffer.append(gDLL->getText("TXT_KEY_BONUS_AVAILABLE_PLAYER", kActivePlayer.getNumAvailableBonuses(eBonus), kActivePlayer.getNameKey()));
+
+ for (int iCorp = 0; iCorp < GC.getNumCorporationInfos(); ++iCorp)
+ {
+ bool bFound = false;
+ if (kActivePlayer.isActiveCorporation((CorporationTypes)iCorp))
+ {
+ for (int i = 0; i < GC.getNUM_CORPORATION_PREREQ_BONUSES(); ++i)
+ {
+ if (eBonus == GC.getCorporationInfo((CorporationTypes)iCorp).getPrereqBonus(i))
+ {
+ int iLoop;
+ for (CvCity* pCity = kActivePlayer.firstCity(&iLoop); NULL != pCity; pCity = kActivePlayer.nextCity(&iLoop))
+ {
+ if (pCity->isHasCorporation((CorporationTypes)iCorp))
+ {
+ bFound = true;
+ break;
+ }
+ }
+ }
+
+ if (bFound)
+ {
+ break;
+ }
+ }
+ }
+
+ if (bFound)
+ {
+ szBuffer.append(GC.getCorporationInfo((CorporationTypes)iCorp).getChar());
+ }
+ }
+ }
+
+ setYieldChangeHelp(szBuffer, L"", L"", L"", GC.getBonusInfo(eBonus).getYieldChangeArray());
+
+ if (GC.getBonusInfo(eBonus).getTechReveal() != NO_TECH)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BONUS_REVEALED_BY", GC.getTechInfo((TechTypes)GC.getBonusInfo(eBonus).getTechReveal()).getTextKeyWide()));
+ }
+ }
+
+ ImprovementTypes eImprovement = NO_IMPROVEMENT;
+ for (int iLoopImprovement = 0; iLoopImprovement < GC.getNumImprovementInfos(); iLoopImprovement++)
+ {
+ if (GC.getImprovementInfo((ImprovementTypes)iLoopImprovement).isImprovementBonusMakesValid(eBonus))
+ {
+ eImprovement = (ImprovementTypes)iLoopImprovement;
+ break;
+ }
+ }
+
+ if (GC.getBonusInfo(eBonus).getHealth() != 0)
+ {
+ if (GC.getBonusInfo(eBonus).getHealth() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BONUS_HEALTHY", GC.getBonusInfo(eBonus).getHealth()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BONUS_UNHEALTHY", -GC.getBonusInfo(eBonus).getHealth()));
+ }
+
+ if (eImprovement != NO_IMPROVEMENT)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_BONUS_WITH_IMPROVEMENT", GC.getImprovementInfo(eImprovement).getTextKeyWide()));
+ }
+ }
+
+ if (GC.getBonusInfo(eBonus).getHappiness() != 0)
+ {
+ if (GC.getBonusInfo(eBonus).getHappiness() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BONUS_HAPPY", GC.getBonusInfo(eBonus).getHappiness()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BONUS_UNHAPPY", -GC.getBonusInfo(eBonus).getHappiness()));
+ }
+
+ if (eImprovement != NO_IMPROVEMENT)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_BONUS_WITH_IMPROVEMENT", GC.getImprovementInfo(eImprovement).getTextKeyWide()));
+ }
+ }
+
+ CivilizationTypes eCivilization = GC.getGameINLINE().getActiveCivilizationType();
+
+ for (int i = 0; i < GC.getNumBuildingClassInfos(); i++)
+ {
+ BuildingTypes eLoopBuilding;
+ if (eCivilization == NO_CIVILIZATION)
+ {
+ eLoopBuilding = ((BuildingTypes)(GC.getBuildingClassInfo((BuildingClassTypes)i).getDefaultBuildingIndex()));
+ }
+ else
+ {
+ eLoopBuilding = ((BuildingTypes)(GC.getCivilizationInfo(eCivilization).getCivilizationBuildings(i)));
+ }
+
+ if (eLoopBuilding != NO_BUILDING)
+ {
+ CvBuildingInfo& kBuilding = GC.getBuildingInfo(eLoopBuilding);
+ if (kBuilding.getBonusHappinessChanges(eBonus) != 0)
+ {
+ if (kBuilding.getBonusHappinessChanges(eBonus) > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BONUS_HAPPY", kBuilding.getBonusHappinessChanges(eBonus)));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BONUS_UNHAPPY", -kBuilding.getBonusHappinessChanges(eBonus)));
+ }
+
+ szBuffer.append(gDLL->getText("TXT_KEY_BONUS_WITH_IMPROVEMENT", kBuilding.getTextKeyWide()));
+ }
+
+ if (kBuilding.getBonusHealthChanges(eBonus) != 0)
+ {
+ if (kBuilding.getBonusHealthChanges(eBonus) > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BONUS_HEALTHY", kBuilding.getBonusHealthChanges(eBonus)));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BONUS_UNHEALTHY", -kBuilding.getBonusHealthChanges(eBonus)));
+ }
+
+ szBuffer.append(gDLL->getText("TXT_KEY_BONUS_WITH_IMPROVEMENT", kBuilding.getTextKeyWide()));
+ }
+ }
+ }
+
+ if (!CvWString(GC.getBonusInfo(eBonus).getHelp()).empty())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(GC.getBonusInfo(eBonus).getHelp());
+ }
+}
+
+void CvGameTextMgr::setReligionHelp(CvWStringBuffer &szBuffer, ReligionTypes eReligion, bool bCivilopedia)
+{
+ UnitTypes eFreeUnit;
+
+ if (NO_RELIGION == eReligion)
+ {
+ return;
+ }
+ CvReligionInfo& religion = GC.getReligionInfo(eReligion);
+
+ if (!bCivilopedia)
+ {
+ szBuffer.append(CvWString::format(SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), religion.getDescription()));
+ }
+
+ setCommerceChangeHelp(szBuffer, gDLL->getText("TXT_KEY_RELIGION_HOLY_CITY").c_str(), L": ", L"", religion.getHolyCityCommerceArray());
+ setCommerceChangeHelp(szBuffer, gDLL->getText("TXT_KEY_RELIGION_ALL_CITIES").c_str(), L": ", L"", religion.getStateReligionCommerceArray());
+
+ if (!bCivilopedia)
+ {
+ if (religion.getTechPrereq() != NO_TECH)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_RELIGION_FOUNDED_FIRST", GC.getTechInfo((TechTypes)religion.getTechPrereq()).getTextKeyWide()));
+ }
+ }
+
+ if (religion.getFreeUnitClass() != NO_UNITCLASS)
+ {
+ if (GC.getGameINLINE().getActivePlayer() != NO_PLAYER)
+ {
+ eFreeUnit = ((UnitTypes)(GC.getCivilizationInfo(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getCivilizationType()).getCivilizationUnits(religion.getFreeUnitClass())));
+ }
+ else
+ {
+ eFreeUnit = (UnitTypes)GC.getUnitClassInfo((UnitClassTypes)religion.getFreeUnitClass()).getDefaultUnitIndex();
+ }
+
+ if (eFreeUnit != NO_UNIT)
+ {
+ if (religion.getNumFreeUnits() > 1)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_RELIGION_FOUNDER_RECEIVES_NUM", GC.getUnitInfo(eFreeUnit).getTextKeyWide(), religion.getNumFreeUnits()));
+ }
+ else if (religion.getNumFreeUnits() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_RELIGION_FOUNDER_RECEIVES", GC.getUnitInfo(eFreeUnit).getTextKeyWide()));
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::setReligionHelpCity(CvWStringBuffer &szBuffer, ReligionTypes eReligion, CvCity *pCity, bool bCityScreen, bool bForceReligion, bool bForceState, bool bNoStateReligion)
+{
+ int i;
+ CvWString szTempBuffer;
+ bool bHandled = false;
+ int iCommerce;
+ int iHappiness;
+ int iProductionModifier;
+ int iFreeExperience;
+ int iGreatPeopleRateModifier;
+
+ if (pCity == NULL)
+ {
+ return;
+ }
+
+ ReligionTypes eStateReligion = (bNoStateReligion ? NO_RELIGION : GET_PLAYER(pCity->getOwnerINLINE()).getStateReligion());
+
+ if (bCityScreen)
+ {
+ szBuffer.append(CvWString::format(SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), GC.getReligionInfo(eReligion).getDescription()));
+ szBuffer.append(NEWLINE);
+
+ if (!(GC.getGameINLINE().isReligionFounded(eReligion)) && !GC.getGameINLINE().isOption(GAMEOPTION_PICK_RELIGION))
+ {
+ if (GC.getReligionInfo(eReligion).getTechPrereq() != NO_TECH)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_RELIGION_FOUNDED_FIRST", GC.getTechInfo((TechTypes)(GC.getReligionInfo(eReligion).getTechPrereq())).getTextKeyWide()));
+ }
+ }
+ }
+
+ if (!bForceReligion)
+ {
+ if (!(pCity->isHasReligion(eReligion)))
+ {
+ return;
+ }
+ }
+
+ if (eStateReligion == eReligion || eStateReligion == NO_RELIGION || bForceState)
+ {
+ for (i = 0; i < NUM_COMMERCE_TYPES; i++)
+ {
+ iCommerce = GC.getReligionInfo(eReligion).getStateReligionCommerce((CommerceTypes)i);
+
+ if (pCity->isHolyCity(eReligion))
+ {
+ iCommerce += GC.getReligionInfo(eReligion).getHolyCityCommerce((CommerceTypes)i);
+ }
+
+ if (iCommerce != 0)
+ {
+ if (bHandled)
+ {
+ szBuffer.append(L", ");
+ }
+
+ szTempBuffer.Format(L"%s%d%c", iCommerce > 0 ? "+" : "", iCommerce, GC.getCommerceInfo((CommerceTypes)i).getChar());
+ szBuffer.append(szTempBuffer);
+ bHandled = true;
+ }
+ }
+ }
+
+ if (eStateReligion == eReligion || bForceState)
+ {
+ iHappiness = (pCity->getStateReligionHappiness(eReligion) + GET_PLAYER(pCity->getOwnerINLINE()).getStateReligionHappiness());
+
+ if (iHappiness != 0)
+ {
+ if (bHandled)
+ {
+ szBuffer.append(L", ");
+ }
+
+ szTempBuffer.Format(L"%d%c", iHappiness, ((iHappiness > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR)));
+ szBuffer.append(szTempBuffer);
+ bHandled = true;
+ }
+
+ iProductionModifier = GET_PLAYER(pCity->getOwnerINLINE()).getStateReligionBuildingProductionModifier();
+ if (iProductionModifier != 0)
+ {
+ if (bHandled)
+ {
+ szBuffer.append(L", ");
+ }
+
+ szBuffer.append(gDLL->getText("TXT_KEY_RELIGION_BUILDING_PROD_MOD", iProductionModifier));
+ bHandled = true;
+ }
+
+ iProductionModifier = GET_PLAYER(pCity->getOwnerINLINE()).getStateReligionUnitProductionModifier();
+ if (iProductionModifier != 0)
+ {
+ if (bHandled)
+ {
+ szBuffer.append(L", ");
+ }
+
+ szBuffer.append(gDLL->getText("TXT_KEY_RELIGION_UNIT_PROD_MOD", iProductionModifier));
+ bHandled = true;
+ }
+
+ iFreeExperience = GET_PLAYER(pCity->getOwnerINLINE()).getStateReligionFreeExperience();
+ if (iFreeExperience != 0)
+ {
+ if (bHandled)
+ {
+ szBuffer.append(L", ");
+ }
+
+ szBuffer.append(gDLL->getText("TXT_KEY_RELIGION_FREE_XP", iFreeExperience));
+ bHandled = true;
+ }
+
+ iGreatPeopleRateModifier = GET_PLAYER(pCity->getOwnerINLINE()).getStateReligionGreatPeopleRateModifier();
+ if (iGreatPeopleRateModifier != 0)
+ {
+ if (bHandled)
+ {
+ szBuffer.append(L", ");
+ }
+
+ szBuffer.append(gDLL->getText("TXT_KEY_RELIGION_BIRTH_RATE_MOD", iGreatPeopleRateModifier));
+ bHandled = true;
+ }
+ }
+}
+
+void CvGameTextMgr::setCorporationHelp(CvWStringBuffer &szBuffer, CorporationTypes eCorporation, bool bCivilopedia)
+{
+ UnitTypes eFreeUnit;
+ CvWString szTempBuffer;
+
+ if (NO_CORPORATION == eCorporation)
+ {
+ return;
+ }
+ CvCorporationInfo& kCorporation = GC.getCorporationInfo(eCorporation);
+
+ if (!bCivilopedia)
+ {
+ szBuffer.append(CvWString::format(SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), kCorporation.getDescription()));
+ }
+
+ szTempBuffer.clear();
+ for (int iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ int iYieldProduced = GC.getCorporationInfo(eCorporation).getYieldProduced((YieldTypes)iI);
+ if (NO_PLAYER != GC.getGameINLINE().getActivePlayer())
+ {
+ iYieldProduced *= GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getCorporationMaintenancePercent();
+ iYieldProduced /= 100;
+ }
+
+ if (iYieldProduced != 0)
+ {
+ if (!szTempBuffer.empty())
+ {
+ szTempBuffer += L", ";
+ }
+
+ if (iYieldProduced % 100 == 0)
+ {
+ szTempBuffer += CvWString::format(L"%s%d%c",
+ iYieldProduced > 0 ? L"+" : L"",
+ iYieldProduced / 100,
+ GC.getYieldInfo((YieldTypes)iI).getChar());
+ }
+ else
+ {
+ szTempBuffer += CvWString::format(L"%s%.2f%c",
+ iYieldProduced > 0 ? L"+" : L"",
+ 0.01f * abs(iYieldProduced),
+ GC.getYieldInfo((YieldTypes)iI).getChar());
+ }
+ }
+ }
+
+ if (!szTempBuffer.empty())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_CORPORATION_ALL_CITIES", szTempBuffer.GetCString()));
+ }
+
+ szTempBuffer.clear();
+ for (int iI = 0; iI < NUM_COMMERCE_TYPES; ++iI)
+ {
+ int iCommerceProduced = GC.getCorporationInfo(eCorporation).getCommerceProduced((CommerceTypes)iI);
+ if (NO_PLAYER != GC.getGameINLINE().getActivePlayer())
+ {
+ iCommerceProduced *= GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getCorporationMaintenancePercent();
+ iCommerceProduced /= 100;
+ }
+ if (iCommerceProduced != 0)
+ {
+ if (!szTempBuffer.empty())
+ {
+ szTempBuffer += L", ";
+ }
+
+ if (iCommerceProduced % 100 == 0)
+ {
+ szTempBuffer += CvWString::format(L"%s%d%c",
+ iCommerceProduced > 0 ? L"+" : L"",
+ iCommerceProduced / 100,
+ GC.getCommerceInfo((CommerceTypes)iI).getChar());
+ }
+ else
+ {
+ szTempBuffer += CvWString::format(L"%s%.2f%c",
+ iCommerceProduced > 0 ? L"+" : L"",
+ 0.01f * abs(iCommerceProduced),
+ GC.getCommerceInfo((CommerceTypes)iI).getChar());
+ }
+
+ }
+ }
+
+ if (!szTempBuffer.empty())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_CORPORATION_ALL_CITIES", szTempBuffer.GetCString()));
+ }
+
+ if (!bCivilopedia)
+ {
+ if (kCorporation.getTechPrereq() != NO_TECH)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_CORPORATION_FOUNDED_FIRST", GC.getTechInfo((TechTypes)kCorporation.getTechPrereq()).getTextKeyWide()));
+ }
+ }
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_CORPORATION_BONUS_REQUIRED"));
+ bool bFirst = true;
+ for (int i = 0; i < GC.getNUM_CORPORATION_PREREQ_BONUSES(); ++i)
+ {
+ if (NO_BONUS != kCorporation.getPrereqBonus(i))
+ {
+ if (bFirst)
+ {
+ bFirst = false;
+ }
+ else
+ {
+ szBuffer.append(L", ");
+ }
+
+ szBuffer.append(CvWString::format(L"%c", GC.getBonusInfo((BonusTypes)kCorporation.getPrereqBonus(i)).getChar()));
+ }
+ }
+
+ if (kCorporation.getBonusProduced() != NO_BONUS)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_CORPORATION_BONUS_PRODUCED", GC.getBonusInfo((BonusTypes)kCorporation.getBonusProduced()).getChar()));
+ }
+
+ if (kCorporation.getFreeUnitClass() != NO_UNITCLASS)
+ {
+ if (GC.getGameINLINE().getActivePlayer() != NO_PLAYER)
+ {
+ eFreeUnit = ((UnitTypes)(GC.getCivilizationInfo(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getCivilizationType()).getCivilizationUnits(kCorporation.getFreeUnitClass())));
+ }
+ else
+ {
+ eFreeUnit = (UnitTypes)GC.getUnitClassInfo((UnitClassTypes)kCorporation.getFreeUnitClass()).getDefaultUnitIndex();
+ }
+
+ if (eFreeUnit != NO_UNIT)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_RELIGION_FOUNDER_RECEIVES", GC.getUnitInfo(eFreeUnit).getTextKeyWide()));
+ }
+ }
+
+ std::vector aCompetingCorps;
+ bFirst = true;
+ for (int iCorporation = 0; iCorporation < GC.getNumCorporationInfos(); ++iCorporation)
+ {
+ if (iCorporation != eCorporation)
+ {
+ bool bCompeting = false;
+
+ CvCorporationInfo& kLoopCorporation = GC.getCorporationInfo((CorporationTypes)iCorporation);
+ for (int i = 0; i < GC.getNUM_CORPORATION_PREREQ_BONUSES(); ++i)
+ {
+ if (kCorporation.getPrereqBonus(i) != NO_BONUS)
+ {
+ for (int j = 0; j < GC.getNUM_CORPORATION_PREREQ_BONUSES(); ++j)
+ {
+ if (kLoopCorporation.getPrereqBonus(j) == kCorporation.getPrereqBonus(i))
+ {
+ bCompeting = true;
+ break;
+ }
+ }
+ }
+
+ if (bCompeting)
+ {
+ break;
+ }
+ }
+
+ if (bCompeting)
+ {
+ CvWString szTemp = CvWString::format(L"%s", kLoopCorporation.getDescription());
+ setListHelp(szBuffer, gDLL->getText("TXT_KEY_CORPORATION_COMPETES").c_str(), szTemp.GetCString(), L", ", bFirst);
+ bFirst = false;
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::setCorporationHelpCity(CvWStringBuffer &szBuffer, CorporationTypes eCorporation, CvCity *pCity, bool bCityScreen, bool bForceCorporation)
+{
+ if (pCity == NULL)
+ {
+ return;
+ }
+
+ CvCorporationInfo& kCorporation = GC.getCorporationInfo(eCorporation);
+
+ if (bCityScreen)
+ {
+ szBuffer.append(CvWString::format(SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), kCorporation.getDescription()));
+ szBuffer.append(NEWLINE);
+
+ if (!(GC.getGameINLINE().isCorporationFounded(eCorporation)))
+ {
+ if (GC.getCorporationInfo(eCorporation).getTechPrereq() != NO_TECH)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_CORPORATION_FOUNDED_FIRST", GC.getTechInfo((TechTypes)(kCorporation.getTechPrereq())).getTextKeyWide()));
+ }
+ }
+ }
+
+ if (!bForceCorporation)
+ {
+ if (!(pCity->isHasCorporation(eCorporation)))
+ {
+ return;
+ }
+ }
+
+ int iNumResources = 0;
+ for (int i = 0; i < GC.getNUM_CORPORATION_PREREQ_BONUSES(); ++i)
+ {
+ BonusTypes eBonus = (BonusTypes)kCorporation.getPrereqBonus(i);
+ if (NO_BONUS != eBonus)
+ {
+ iNumResources += pCity->getNumBonuses(eBonus);
+ }
+ }
+
+ bool bActive = (pCity->isActiveCorporation(eCorporation) || (bForceCorporation && iNumResources > 0));
+
+ bool bHandled = false;
+ for (int i = 0; i < NUM_YIELD_TYPES; ++i)
+ {
+ int iYield = 0;
+
+ if (bActive)
+ {
+ iYield += (kCorporation.getYieldProduced(i) * iNumResources * GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getCorporationMaintenancePercent()) / 100;
+ }
+
+ if (iYield != 0)
+ {
+ if (bHandled)
+ {
+ szBuffer.append(L", ");
+ }
+
+ CvWString szTempBuffer;
+ szTempBuffer.Format(L"%s%d%c", iYield > 0 ? "+" : "", (iYield + 99) / 100, GC.getYieldInfo((YieldTypes)i).getChar());
+ szBuffer.append(szTempBuffer);
+ bHandled = true;
+ }
+ }
+
+ bHandled = false;
+ for (int i = 0; i < NUM_COMMERCE_TYPES; ++i)
+ {
+ int iCommerce = 0;
+
+ if (bActive)
+ {
+ iCommerce += (kCorporation.getCommerceProduced(i) * iNumResources * GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getCorporationMaintenancePercent()) / 100;
+ }
+
+ if (iCommerce != 0)
+ {
+ if (bHandled)
+ {
+ szBuffer.append(L", ");
+ }
+
+ CvWString szTempBuffer;
+ szTempBuffer.Format(L"%s%d%c", iCommerce > 0 ? "+" : "", (iCommerce + 99) / 100, GC.getCommerceInfo((CommerceTypes)i).getChar());
+ szBuffer.append(szTempBuffer);
+ bHandled = true;
+ }
+ }
+
+ int iMaintenance = 0;
+
+ if (bActive)
+ {
+ iMaintenance += pCity->calculateCorporationMaintenanceTimes100(eCorporation);
+ iMaintenance *= 100 + pCity->getMaintenanceModifier();
+ iMaintenance /= 100;
+ }
+
+ if (0 != iMaintenance)
+ {
+ if (bHandled)
+ {
+ szBuffer.append(L", ");
+ }
+
+ CvWString szTempBuffer;
+ szTempBuffer.Format(L"%d%c", -iMaintenance / 100, GC.getCommerceInfo(COMMERCE_GOLD).getChar());
+ szBuffer.append(szTempBuffer);
+ bHandled = true;
+ }
+
+ if (bCityScreen)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_CORPORATION_BONUS_REQUIRED"));
+ bool bFirst = true;
+ for (int i = 0; i < GC.getNUM_CORPORATION_PREREQ_BONUSES(); ++i)
+ {
+ if (NO_BONUS != kCorporation.getPrereqBonus(i))
+ {
+ if (bFirst)
+ {
+ bFirst = false;
+ }
+ else
+ {
+ szBuffer.append(L", ");
+ }
+
+ szBuffer.append(CvWString::format(L"%c", GC.getBonusInfo((BonusTypes)kCorporation.getPrereqBonus(i)).getChar()));
+ }
+ }
+
+ if (bActive)
+ {
+ if (kCorporation.getBonusProduced() != NO_BONUS)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_CORPORATION_BONUS_PRODUCED", GC.getBonusInfo((BonusTypes)kCorporation.getBonusProduced()).getChar()));
+ }
+ }
+ }
+ else
+ {
+ if (kCorporation.getBonusProduced() != NO_BONUS)
+ {
+ if (bActive)
+ {
+ if (bHandled)
+ {
+ szBuffer.append(L", ");
+ }
+
+ szBuffer.append(CvWString::format(L"%c", GC.getBonusInfo((BonusTypes)kCorporation.getBonusProduced()).getChar()));
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::buildObsoleteString(CvWStringBuffer &szBuffer, int iItem, bool bList, bool bPlayerContext)
+{
+ CvWString szTempBuffer;
+
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_TECH_OBSOLETES", GC.getBuildingInfo((BuildingTypes) iItem).getTextKeyWide()));
+}
+
+void CvGameTextMgr::buildObsoleteBonusString(CvWStringBuffer &szBuffer, int iItem, bool bList, bool bPlayerContext)
+{
+ CvWString szTempBuffer;
+
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_TECH_OBSOLETES", GC.getBonusInfo((BonusTypes) iItem).getTextKeyWide()));
+}
+
+void CvGameTextMgr::buildObsoleteSpecialString(CvWStringBuffer &szBuffer, int iItem, bool bList, bool bPlayerContext)
+{
+ CvWString szTempBuffer;
+
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_TECH_OBSOLETES_NO_LINK", GC.getSpecialBuildingInfo((SpecialBuildingTypes) iItem).getTextKeyWide()));
+}
+
+void CvGameTextMgr::buildMoveString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ int iI;
+ int iMoveDiff;
+
+ for (iI = 0; iI < GC.getNumRouteInfos(); ++iI)
+ {
+ iMoveDiff = ((GC.getMOVE_DENOMINATOR() / std::max(1, (GC.getRouteInfo((RouteTypes) iI).getMovementCost() + ((bPlayerContext) ? GET_TEAM(GC.getGameINLINE().getActiveTeam()).getRouteChange((RouteTypes)iI) : 0)))) - (GC.getMOVE_DENOMINATOR() / std::max(1, (GC.getRouteInfo((RouteTypes) iI).getMovementCost() + ((bPlayerContext) ? GET_TEAM(GC.getGameINLINE().getActiveTeam()).getRouteChange((RouteTypes)iI) : 0) + GC.getRouteInfo((RouteTypes) iI).getTechMovementChange(eTech)))));
+
+ if (iMoveDiff != 0)
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_MOVEMENT", -(iMoveDiff), GC.getRouteInfo((RouteTypes) iI).getTextKeyWide()));
+ bList = true;
+ }
+ }
+}
+
+void CvGameTextMgr::buildFreeUnitString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ UnitTypes eFreeUnit = NO_UNIT;
+ if (GC.getGameINLINE().getActivePlayer() != NO_PLAYER)
+ {
+ eFreeUnit = GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getTechFreeUnit(eTech);
+ }
+ else
+ {
+ if (GC.getTechInfo(eTech).getFirstFreeUnitClass() != NO_UNITCLASS)
+ {
+ eFreeUnit = (UnitTypes)GC.getUnitClassInfo((UnitClassTypes)GC.getTechInfo(eTech).getFirstFreeUnitClass()).getDefaultUnitIndex();
+ }
+ }
+
+ if (eFreeUnit != NO_UNIT)
+ {
+ if (!bPlayerContext || (GC.getGameINLINE().countKnownTechNumTeams(eTech) == 0))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_TECH_FIRST_RECEIVES", GC.getUnitInfo(eFreeUnit).getTextKeyWide()));
+ }
+ }
+}
+
+void CvGameTextMgr::buildFeatureProductionString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).getFeatureProductionModifier() != 0)
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_FEATURE_PRODUCTION_MODIFIER", GC.getTechInfo(eTech).getFeatureProductionModifier()));
+ }
+}
+
+void CvGameTextMgr::buildWorkerRateString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).getWorkerSpeedModifier() != 0)
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_WORKERS_FASTER", GC.getTechInfo(eTech).getWorkerSpeedModifier()));
+ }
+}
+
+void CvGameTextMgr::buildTradeRouteString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).getTradeRoutes() != 0)
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_TRADE_ROUTES", GC.getTechInfo(eTech).getTradeRoutes()));
+ }
+}
+
+void CvGameTextMgr::buildHealthRateString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).getHealth() != 0)
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HEALTH_ALL_CITIES", abs(GC.getTechInfo(eTech).getHealth()), ((GC.getTechInfo(eTech).getHealth() > 0) ? gDLL->getSymbolID(HEALTHY_CHAR): gDLL->getSymbolID(UNHEALTHY_CHAR))));
+ }
+}
+
+void CvGameTextMgr::buildHappinessRateString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).getHappiness() != 0)
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HAPPINESS_ALL_CITIES", abs(GC.getTechInfo(eTech).getHappiness()), ((GC.getTechInfo(eTech).getHappiness() > 0) ? gDLL->getSymbolID(HAPPY_CHAR): gDLL->getSymbolID(UNHAPPY_CHAR))));
+ }
+}
+
+void CvGameTextMgr::buildFreeTechString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).getFirstFreeTechs() > 0)
+ {
+ if (!bPlayerContext || (GC.getGameINLINE().countKnownTechNumTeams(eTech) == 0))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+
+ if (GC.getTechInfo(eTech).getFirstFreeTechs() == 1)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_TECH_FIRST_FREE_TECH"));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_TECH_FIRST_FREE_TECHS", GC.getTechInfo(eTech).getFirstFreeTechs()));
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::buildLOSString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isExtraWaterSeeFrom() && (!bPlayerContext || !(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isExtraWaterSeeFrom())))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_UNIT_EXTRA_SIGHT"));
+ }
+}
+
+void CvGameTextMgr::buildMapCenterString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isMapCentering() && (!bPlayerContext || !(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isMapCentering())))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_CENTERS_MAP"));
+ }
+}
+
+void CvGameTextMgr::buildMapRevealString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList)
+{
+ if (GC.getTechInfo(eTech).isMapVisible())
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_REVEALS_MAP"));
+ }
+}
+
+void CvGameTextMgr::buildMapTradeString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isMapTrading() && (!bPlayerContext || !(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isMapTrading())))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ENABLES_MAP_TRADING"));
+ }
+}
+
+void CvGameTextMgr::buildTechTradeString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isTechTrading() && (!bPlayerContext || !(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isTechTrading())))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ENABLES_TECH_TRADING"));
+ }
+}
+
+void CvGameTextMgr::buildGoldTradeString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isGoldTrading() && (!bPlayerContext || !(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isGoldTrading())))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ENABLES_GOLD_TRADING"));
+ }
+}
+
+void CvGameTextMgr::buildOpenBordersString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isOpenBordersTrading() && (!bPlayerContext || !(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isOpenBordersTrading())))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ENABLES_OPEN_BORDERS"));
+ }
+}
+
+void CvGameTextMgr::buildDefensivePactString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isDefensivePactTrading() && (!bPlayerContext || !(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isDefensivePactTrading())))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ENABLES_DEFENSIVE_PACTS"));
+ }
+}
+
+void CvGameTextMgr::buildPermanentAllianceString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isPermanentAllianceTrading() && (!bPlayerContext || (!(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isPermanentAllianceTrading()) && GC.getGameINLINE().isOption(GAMEOPTION_PERMANENT_ALLIANCES))))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ENABLES_PERM_ALLIANCES"));
+ }
+}
+
+void CvGameTextMgr::buildVassalStateString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isVassalStateTrading() && (!bPlayerContext || (!(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isVassalStateTrading()) && GC.getGameINLINE().isOption(GAMEOPTION_NO_VASSAL_STATES))))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ENABLES_VASSAL_STATES"));
+ }
+}
+
+void CvGameTextMgr::buildBridgeString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isBridgeBuilding() && (!bPlayerContext || !(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isBridgeBuilding())))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ENABLES_BRIDGE_BUILDING"));
+ }
+}
+
+void CvGameTextMgr::buildIrrigationString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isIrrigation() && (!bPlayerContext || !(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isIrrigation())))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_SPREAD_IRRIGATION"));
+ }
+}
+
+void CvGameTextMgr::buildIgnoreIrrigationString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isIgnoreIrrigation() && (!bPlayerContext || !(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isIgnoreIrrigation())))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_IRRIGATION_ANYWHERE"));
+ }
+}
+
+void CvGameTextMgr::buildWaterWorkString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isWaterWork() && (!bPlayerContext || !(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isWaterWork())))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_WATER_WORK"));
+ }
+}
+
+void CvGameTextMgr::buildImprovementString(CvWStringBuffer &szBuffer, TechTypes eTech, int iImprovement, bool bList, bool bPlayerContext)
+{
+ bool bTechFound;
+ int iJ;
+
+ bTechFound = false;
+
+ if (GC.getBuildInfo((BuildTypes) iImprovement).getTechPrereq() == NO_TECH)
+ {
+ for (iJ = 0; iJ < GC.getNumFeatureInfos(); iJ++)
+ {
+ if (GC.getBuildInfo((BuildTypes) iImprovement).getFeatureTech(iJ) == eTech)
+ {
+ bTechFound = true;
+ }
+ }
+ }
+ else
+ {
+ if (GC.getBuildInfo((BuildTypes) iImprovement).getTechPrereq() == eTech)
+ {
+ bTechFound = true;
+ }
+ }
+
+ if (bTechFound)
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_CAN_BUILD_IMPROVEMENT", GC.getBuildInfo((BuildTypes) iImprovement).getTextKeyWide()));
+ }
+}
+
+void CvGameTextMgr::buildDomainExtraMovesString(CvWStringBuffer &szBuffer, TechTypes eTech, int iDomainType, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).getDomainExtraMoves(iDomainType) != 0)
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_EXTRA_MOVES", GC.getTechInfo(eTech).getDomainExtraMoves(iDomainType), GC.getDomainInfo((DomainTypes)iDomainType).getTextKeyWide()));
+ }
+}
+
+void CvGameTextMgr::buildAdjustString(CvWStringBuffer &szBuffer, TechTypes eTech, int iCommerceType, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isCommerceFlexible(iCommerceType) && (!bPlayerContext || !(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isCommerceFlexible((CommerceTypes)iCommerceType))))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ADJUST_COMMERCE_RATE", GC.getCommerceInfo((CommerceTypes) iCommerceType).getChar()));
+ }
+}
+
+void CvGameTextMgr::buildTerrainTradeString(CvWStringBuffer &szBuffer, TechTypes eTech, int iTerrainType, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isTerrainTrade(iTerrainType) && (!bPlayerContext || !(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isTerrainTrade((TerrainTypes)iTerrainType))))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ENABLES_ON_TERRAIN", gDLL->getSymbolID(TRADE_CHAR), GC.getTerrainInfo((TerrainTypes) iTerrainType).getTextKeyWide()));
+ }
+}
+
+void CvGameTextMgr::buildRiverTradeString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bList, bool bPlayerContext)
+{
+ if (GC.getTechInfo(eTech).isRiverTrade() && (!bPlayerContext || !(GET_TEAM(GC.getGameINLINE().getActiveTeam()).isRiverTrade())))
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ENABLES_ON_TERRAIN", gDLL->getSymbolID(TRADE_CHAR), gDLL->getText("TXT_KEY_MISC_RIVERS").GetCString()));
+ }
+}
+
+void CvGameTextMgr::buildSpecialBuildingString(CvWStringBuffer &szBuffer, TechTypes eTech, int iBuildingType, bool bList, bool bPlayerContext)
+{
+ if (GC.getSpecialBuildingInfo((SpecialBuildingTypes)iBuildingType).getTechPrereq() == eTech)
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_CAN_CONSTRUCT_BUILDING", GC.getSpecialBuildingInfo((SpecialBuildingTypes) iBuildingType).getTextKeyWide()));
+ }
+
+ if (GC.getSpecialBuildingInfo((SpecialBuildingTypes)iBuildingType).getTechPrereqAnyone() == eTech)
+ {
+ if (bList)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_CAN_CONSTRUCT_BUILDING_ANYONE", GC.getSpecialBuildingInfo((SpecialBuildingTypes) iBuildingType).getTextKeyWide()));
+ }
+}
+
+void CvGameTextMgr::buildYieldChangeString(CvWStringBuffer &szBuffer, TechTypes eTech, int iYieldType, bool bList, bool bPlayerContext)
+{
+ CvWString szTempBuffer;
+ if (bList)
+ {
+ szTempBuffer.Format(L"%s", GC.getImprovementInfo((ImprovementTypes)iYieldType).getDescription());
+ }
+ else
+ {
+ szTempBuffer.Format(L"%c%s", gDLL->getSymbolID(BULLET_CHAR), GC.getImprovementInfo((ImprovementTypes)iYieldType).getDescription());
+ }
+
+ setYieldChangeHelp(szBuffer, szTempBuffer, L": ", L"", GC.getImprovementInfo((ImprovementTypes)iYieldType).getTechYieldChangesArray(eTech), false, bList);
+}
+
+bool CvGameTextMgr::buildBonusRevealString(CvWStringBuffer &szBuffer, TechTypes eTech, int iBonusType, bool bFirst, bool bList, bool bPlayerContext)
+{
+ CvWString szTempBuffer;
+
+ if (GC.getBonusInfo((BonusTypes) iBonusType).getTechReveal() == eTech)
+ {
+ if (bList && bFirst)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), GC.getBonusInfo((BonusTypes) iBonusType).getDescription());
+ setListHelp(szBuffer, gDLL->getText("TXT_KEY_MISC_REVEALS").c_str(), szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ return bFirst;
+}
+
+bool CvGameTextMgr::buildCivicRevealString(CvWStringBuffer &szBuffer, TechTypes eTech, int iCivicType, bool bFirst, bool bList, bool bPlayerContext)
+{
+ CvWString szTempBuffer;
+
+ if (GC.getCivicInfo((CivicTypes) iCivicType).getTechPrereq() == eTech)
+ {
+ if (bList && bFirst)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), GC.getCivicInfo((CivicTypes) iCivicType).getDescription());
+ setListHelp(szBuffer, gDLL->getText("TXT_KEY_MISC_ENABLES").c_str(), szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ return bFirst;
+}
+
+bool CvGameTextMgr::buildProcessInfoString(CvWStringBuffer &szBuffer, TechTypes eTech, int iProcessType, bool bFirst, bool bList, bool bPlayerContext)
+{
+ CvWString szTempBuffer;
+
+ if (GC.getProcessInfo((ProcessTypes) iProcessType).getTechPrereq() == eTech)
+ {
+ if (bList && bFirst)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), GC.getProcessInfo((ProcessTypes) iProcessType).getDescription());
+ setListHelp(szBuffer, gDLL->getText("TXT_KEY_MISC_CAN_BUILD").c_str(), szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ return bFirst;
+}
+
+bool CvGameTextMgr::buildFoundReligionString(CvWStringBuffer &szBuffer, TechTypes eTech, int iReligionType, bool bFirst, bool bList, bool bPlayerContext)
+{
+ CvWString szTempBuffer;
+
+ if (GC.getReligionInfo((ReligionTypes) iReligionType).getTechPrereq() == eTech)
+ {
+ if (!bPlayerContext || (GC.getGameINLINE().countKnownTechNumTeams(eTech) == 0))
+ {
+ if (bList && bFirst)
+ {
+ szBuffer.append(NEWLINE);
+ }
+
+ if (GC.getGameINLINE().isOption(GAMEOPTION_PICK_RELIGION))
+ {
+ szTempBuffer = gDLL->getText("TXT_KEY_RELIGION_UNKNOWN");
+ }
+ else
+ {
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), GC.getReligionInfo((ReligionTypes) iReligionType).getDescription());
+ }
+ setListHelp(szBuffer, gDLL->getText("TXT_KEY_MISC_FIRST_DISCOVER_FOUNDS").c_str(), szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+ return bFirst;
+}
+
+bool CvGameTextMgr::buildFoundCorporationString(CvWStringBuffer &szBuffer, TechTypes eTech, int iCorporationType, bool bFirst, bool bList, bool bPlayerContext)
+{
+ CvWString szTempBuffer;
+
+ if (GC.getCorporationInfo((CorporationTypes) iCorporationType).getTechPrereq() == eTech)
+ {
+ if (!bPlayerContext || (GC.getGameINLINE().countKnownTechNumTeams(eTech) == 0))
+ {
+ if (bList && bFirst)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), GC.getCorporationInfo((CorporationTypes) iCorporationType).getDescription());
+ setListHelp(szBuffer, gDLL->getText("TXT_KEY_MISC_FIRST_DISCOVER_INCORPORATES").c_str(), szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+ return bFirst;
+}
+
+bool CvGameTextMgr::buildPromotionString(CvWStringBuffer &szBuffer, TechTypes eTech, int iPromotionType, bool bFirst, bool bList, bool bPlayerContext)
+{
+ CvWString szTempBuffer;
+
+ if (GC.getPromotionInfo((PromotionTypes) iPromotionType).getTechPrereq() == eTech)
+ {
+ if (bList && bFirst)
+ {
+ szBuffer.append(NEWLINE);
+ }
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), GC.getPromotionInfo((PromotionTypes) iPromotionType).getDescription());
+ setListHelp(szBuffer, gDLL->getText("TXT_KEY_MISC_ENABLES").c_str(), szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ return bFirst;
+}
+
+// Displays a list of derived technologies - no distinction between AND/OR prerequisites
+void CvGameTextMgr::buildSingleLineTechTreeString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bPlayerContext)
+{
+ CvWString szTempBuffer; // Formatting
+
+ if (NO_TECH == eTech)
+ {
+ // you need to specify a tech of origin for this method to do anything
+ return;
+ }
+
+ bool bFirst = true;
+ for (int iI = 0; iI < GC.getNumTechInfos(); ++iI)
+ {
+ bool bTechAlreadyAccessible = false;
+ if (bPlayerContext)
+ {
+ bTechAlreadyAccessible = (GET_TEAM(GC.getGameINLINE().getActiveTeam()).isHasTech((TechTypes)iI) || GET_PLAYER(GC.getGameINLINE().getActivePlayer()).canResearch((TechTypes)iI));
+ }
+ if (!bTechAlreadyAccessible)
+ {
+ bool bTechFound = false;
+
+ if (!bTechFound)
+ {
+ for (int iJ = 0; iJ < GC.getNUM_OR_TECH_PREREQS(); iJ++)
+ {
+ if (GC.getTechInfo((TechTypes) iI).getPrereqOrTechs(iJ) == eTech)
+ {
+ bTechFound = true;
+ break;
+ }
+ }
+ }
+
+ if (!bTechFound)
+ {
+ for (int iJ = 0; iJ < GC.getNUM_AND_TECH_PREREQS(); iJ++)
+ {
+ if (GC.getTechInfo((TechTypes) iI).getPrereqAndTechs(iJ) == eTech)
+ {
+ bTechFound = true;
+ break;
+ }
+ }
+ }
+
+ if (bTechFound)
+ {
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_TECH_TEXT"), GC.getTechInfo((TechTypes) iI).getDescription());
+ setListHelp(szBuffer, gDLL->getText("TXT_KEY_MISC_LEADS_TO").c_str(), szTempBuffer, L", ", bFirst);
+ bFirst = false;
+ }
+ }
+ }
+}
+
+// Information about other prerequisite technologies to eTech besides eFromTech
+void CvGameTextMgr::buildTechTreeString(CvWStringBuffer &szBuffer, TechTypes eTech, bool bPlayerContext, TechTypes eFromTech)
+{
+ CvWString szTempBuffer; // Formatting
+
+ if (NO_TECH == eTech || NO_TECH == eFromTech)
+ {
+ return;
+ }
+
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR("COLOR_TECH_TEXT"), GC.getTechInfo(eTech).getDescription());
+ szBuffer.append(szTempBuffer);
+
+ // Loop through OR prerequisites to make list
+ CvWString szOtherOrTechs;
+ int nOtherOrTechs = 0;
+ bool bOrTechFound = false;
+ for (int iJ = 0; iJ < GC.getNUM_OR_TECH_PREREQS(); iJ++)
+ {
+ TechTypes eTestTech = (TechTypes)GC.getTechInfo(eTech).getPrereqOrTechs(iJ);
+ if (eTestTech >= 0)
+ {
+ bool bTechAlreadyResearched = false;
+ if (bPlayerContext)
+ {
+ bTechAlreadyResearched = GET_TEAM(GC.getGameINLINE().getActiveTeam()).isHasTech(eTestTech);
+ }
+ if (!bTechAlreadyResearched)
+ {
+ if (eTestTech == eFromTech)
+ {
+ bOrTechFound = true;
+ }
+ else
+ {
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_TECH_TEXT"), GC.getTechInfo(eTestTech).getDescription());
+ setListHelp(szOtherOrTechs, L"", szTempBuffer, gDLL->getText("TXT_KEY_OR").c_str(), 0 == nOtherOrTechs);
+ nOtherOrTechs++;
+ }
+ }
+ }
+ }
+
+ // Loop through AND prerequisites to make list
+ CvWString szOtherAndTechs;
+ int nOtherAndTechs = 0;
+ bool bAndTechFound = false;
+ for (int iJ = 0; iJ < GC.getNUM_AND_TECH_PREREQS(); iJ++)
+ {
+ TechTypes eTestTech = (TechTypes)GC.getTechInfo(eTech).getPrereqAndTechs(iJ);
+ if (eTestTech >= 0)
+ {
+ bool bTechAlreadyResearched = false;
+ if (bPlayerContext)
+ {
+ bTechAlreadyResearched = GET_TEAM(GC.getGameINLINE().getActiveTeam()).isHasTech(eTestTech);
+ }
+ if (!bTechAlreadyResearched)
+ {
+ if (eTestTech == eFromTech)
+ {
+ bAndTechFound = true;
+ }
+ else
+ {
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_TECH_TEXT"), GC.getTechInfo(eTestTech).getDescription());
+ setListHelp(szOtherAndTechs, L"", szTempBuffer, L", ", 0 == nOtherAndTechs);
+ nOtherAndTechs++;
+ }
+ }
+ }
+ }
+
+ if (bOrTechFound || bAndTechFound)
+ {
+ if (nOtherAndTechs > 0 || nOtherOrTechs > 0)
+ {
+ szBuffer.append(L' ');
+
+ if (nOtherAndTechs > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_WITH_SPACE"));
+ szBuffer.append(szOtherAndTechs);
+ }
+
+ if (nOtherOrTechs > 0)
+ {
+ if (bAndTechFound)
+ {
+ if (nOtherAndTechs > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_AND_SPACE"));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_WITH_SPACE"));
+ }
+ szBuffer.append(szOtherOrTechs);
+ }
+ else if (bOrTechFound)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ALTERNATIVELY_DERIVED", GC.getTechInfo(eTech).getTextKeyWide(), szOtherOrTechs.GetCString()));
+ }
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::setPromotionHelp(CvWStringBuffer &szBuffer, PromotionTypes ePromotion, bool bCivilopediaText)
+{
+ if (!bCivilopediaText)
+ {
+ CvWString szTempBuffer;
+
+ if (NO_PROMOTION == ePromotion)
+ {
+ return;
+ }
+ CvPromotionInfo& promo = GC.getPromotionInfo(ePromotion);
+
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), promo.getDescription());
+ szBuffer.append(szTempBuffer);
+ }
+
+ parsePromotionHelp(szBuffer, ePromotion);
+}
+
+void CvGameTextMgr::setUnitCombatHelp(CvWStringBuffer &szBuffer, UnitCombatTypes eUnitCombat)
+{
+ szBuffer.append(GC.getUnitCombatInfo(eUnitCombat).getDescription());
+}
+
+void CvGameTextMgr::setImprovementHelp(CvWStringBuffer &szBuffer, ImprovementTypes eImprovement, bool bCivilopediaText)
+{
+ CvWString szTempBuffer;
+ CvWString szFirstBuffer;
+ int iTurns;
+
+ if (NO_IMPROVEMENT == eImprovement)
+ {
+ return;
+ }
+
+ CvImprovementInfo& info = GC.getImprovementInfo(eImprovement);
+ if (!bCivilopediaText)
+ {
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR, TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), info.getDescription());
+ szBuffer.append(szTempBuffer);
+
+ setYieldChangeHelp(szBuffer, L", ", L"", L"", info.getYieldChangeArray(), false, false);
+
+ setYieldChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_MISC_WITH_IRRIGATION").c_str(), info.getIrrigatedYieldChangeArray());
+ setYieldChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_MISC_ON_HILLS").c_str(), info.getHillsYieldChangeArray());
+ setYieldChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_MISC_ALONG_RIVER").c_str(), info.getRiverSideYieldChangeArray());
+
+ for (int iTech = 0; iTech < GC.getNumTechInfos(); iTech++)
+ {
+ for (int iYield = 0; iYield < NUM_YIELD_TYPES; iYield++)
+ {
+ if (0 != info.getTechYieldChanges(iTech, iYield))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_IMPROVEMENT_WITH_TECH", info.getTechYieldChanges(iTech, iYield), GC.getYieldInfo((YieldTypes)iYield).getChar(), GC.getTechInfo((TechTypes)iTech).getTextKeyWide()));
+ }
+ }
+ }
+
+ // Civics
+ for (int iYield = 0; iYield < NUM_YIELD_TYPES; iYield++)
+ {
+ for (int iCivic = 0; iCivic < GC.getNumCivicInfos(); iCivic++)
+ {
+ int iChange = GC.getCivicInfo((CivicTypes)iCivic).getImprovementYieldChanges(eImprovement, iYield);
+ if (0 != iChange)
+ {
+ szTempBuffer.Format( SETCOLR L"%s" ENDCOLR , TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), GC.getCivicInfo((CivicTypes)iCivic).getDescription());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_CIVIC_IMPROVEMENT_YIELD_CHANGE", iChange, GC.getYieldInfo((YieldTypes)iYield).getChar()));
+ szBuffer.append(szTempBuffer);
+ }
+ }
+ }
+ }
+
+ if (info.isRequiresRiverSide())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_IMPROVEMENT_REQUIRES_RIVER"));
+ }
+ if (info.isCarriesIrrigation())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_IMPROVEMENT_CARRIES_IRRIGATION"));
+ }
+ if (bCivilopediaText)
+ {
+ if (info.isNoFreshWater())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_IMPROVEMENT_NO_BUILD_FRESH_WATER"));
+ }
+ if (info.isWater())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_IMPROVEMENT_BUILD_ONLY_WATER"));
+ }
+ if (info.isRequiresFlatlands())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_IMPROVEMENT_ONLY_BUILD_FLATLANDS"));
+ }
+ }
+
+ if (info.getImprovementUpgrade() != NO_IMPROVEMENT)
+ {
+ iTurns = GC.getGameINLINE().getImprovementUpgradeTime(eImprovement);
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_IMPROVEMENT_EVOLVES", GC.getImprovementInfo((ImprovementTypes) info.getImprovementUpgrade()).getTextKeyWide(), iTurns));
+ }
+
+ int iLast = -1;
+ for (int iBonus = 0; iBonus < GC.getNumBonusInfos(); iBonus++)
+ {
+ int iRand = info.getImprovementBonusDiscoverRand(iBonus);
+ if (iRand > 0)
+ {
+ szFirstBuffer.Format(L"%s%s", NEWLINE, gDLL->getText("TXT_KEY_IMPROVEMENT_CHANCE_DISCOVER").c_str());
+ szTempBuffer.Format(L"%c", GC.getBonusInfo((BonusTypes) iBonus).getChar());
+ setListHelp(szBuffer, szFirstBuffer, szTempBuffer, L", ", iRand != iLast);
+ iLast = iRand;
+ }
+ }
+
+ if (0 != info.getDefenseModifier())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_IMPROVEMENT_DEFENSE_MODIFIER", info.getDefenseModifier()));
+ }
+
+ if (0 != info.getHappiness())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ICON_CHANGE_NEARBY_CITIES", info.getHappiness(), (info.getHappiness() > 0 ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR))));
+ }
+
+ if (info.isActsAsCity())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_IMPROVEMENT_DEFENSE_MODIFIER_EXTRA"));
+ }
+
+ if (info.getFeatureGrowthProbability() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_IMPROVEMENT_MORE_GROWTH"));
+ }
+ else if (info.getFeatureGrowthProbability() < 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_IMPROVEMENT_LESS_GROWTH"));
+ }
+
+ if (bCivilopediaText)
+ {
+ if (info.getPillageGold() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_IMPROVEMENT_PILLAGE_YIELDS", info.getPillageGold()));
+ }
+ }
+}
+
+
+void CvGameTextMgr::getDealString(CvWStringBuffer& szBuffer, CvDeal& deal, PlayerTypes ePlayerPerspective)
+{
+ PlayerTypes ePlayer1 = deal.getFirstPlayer();
+ PlayerTypes ePlayer2 = deal.getSecondPlayer();
+
+ const CLinkList* pListPlayer1 = deal.getFirstTrades();
+ const CLinkList* pListPlayer2 = deal.getSecondTrades();
+
+ getDealString(szBuffer, ePlayer1, ePlayer2, pListPlayer1, pListPlayer2, ePlayerPerspective);
+}
+
+void CvGameTextMgr::getDealString(CvWStringBuffer& szBuffer, PlayerTypes ePlayer1, PlayerTypes ePlayer2, const CLinkList* pListPlayer1, const CLinkList* pListPlayer2, PlayerTypes ePlayerPerspective)
+{
+ if (NO_PLAYER == ePlayer1 || NO_PLAYER == ePlayer2)
+ {
+ FAssertMsg(false, "Deal needs two parties");
+ return;
+ }
+
+ CvWStringBuffer szDealOne;
+ if (NULL != pListPlayer1 && pListPlayer1->getLength() > 0)
+ {
+ CLLNode* pTradeNode;
+ bool bFirst = true;
+ for (pTradeNode = pListPlayer1->head(); pTradeNode; pTradeNode = pListPlayer1->next(pTradeNode))
+ {
+ CvWStringBuffer szTrade;
+ getTradeString(szTrade, pTradeNode->m_data, ePlayer1, ePlayer2);
+ setListHelp(szDealOne, L"", szTrade.getCString(), L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ CvWStringBuffer szDealTwo;
+ if (NULL != pListPlayer2 && pListPlayer2->getLength() > 0)
+ {
+ CLLNode* pTradeNode;
+ bool bFirst = true;
+ for (pTradeNode = pListPlayer2->head(); pTradeNode; pTradeNode = pListPlayer2->next(pTradeNode))
+ {
+ CvWStringBuffer szTrade;
+ getTradeString(szTrade, pTradeNode->m_data, ePlayer2, ePlayer1);
+ setListHelp(szDealTwo, L"", szTrade.getCString(), L", ", bFirst);
+ bFirst = false;
+ }
+ }
+
+ if (!szDealOne.isEmpty())
+ {
+ if (!szDealTwo.isEmpty())
+ {
+ if (ePlayerPerspective == ePlayer1)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_OUR_DEAL", szDealOne.getCString(), GET_PLAYER(ePlayer2).getNameKey(), szDealTwo.getCString()));
+ }
+ else if (ePlayerPerspective == ePlayer2)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_OUR_DEAL", szDealTwo.getCString(), GET_PLAYER(ePlayer1).getNameKey(), szDealOne.getCString()));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_DEAL", GET_PLAYER(ePlayer1).getNameKey(), szDealOne.getCString(), GET_PLAYER(ePlayer2).getNameKey(), szDealTwo.getCString()));
+ }
+ }
+ else
+ {
+ if (ePlayerPerspective == ePlayer1)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_DEAL_ONESIDED_OURS", szDealOne.getCString(), GET_PLAYER(ePlayer2).getNameKey()));
+ }
+ else if (ePlayerPerspective == ePlayer2)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_DEAL_ONESIDED_THEIRS", szDealOne.getCString(), GET_PLAYER(ePlayer1).getNameKey()));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_DEAL_ONESIDED", GET_PLAYER(ePlayer1).getNameKey(), szDealOne.getCString(), GET_PLAYER(ePlayer2).getNameKey()));
+ }
+ }
+ }
+ else if (!szDealTwo.isEmpty())
+ {
+ if (ePlayerPerspective == ePlayer1)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_DEAL_ONESIDED_THEIRS", szDealTwo.getCString(), GET_PLAYER(ePlayer2).getNameKey()));
+ }
+ else if (ePlayerPerspective == ePlayer2)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_DEAL_ONESIDED_OURS", szDealTwo.getCString(), GET_PLAYER(ePlayer1).getNameKey()));
+ }
+ else
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_DEAL_ONESIDED", GET_PLAYER(ePlayer2).getNameKey(), szDealTwo.getCString(), GET_PLAYER(ePlayer1).getNameKey()));
+ }
+ }
+}
+
+void CvGameTextMgr::getWarplanString(CvWStringBuffer& szString, WarPlanTypes eWarPlan)
+{
+ switch (eWarPlan)
+ {
+ case WARPLAN_ATTACKED_RECENT: szString.assign(L"new defensive war"); break;
+ case WARPLAN_ATTACKED: szString.assign(L"defensive war"); break;
+ case WARPLAN_PREPARING_LIMITED: szString.assign(L"preparing limited war"); break;
+ case WARPLAN_PREPARING_TOTAL: szString.assign(L"preparing total war"); break;
+ case WARPLAN_LIMITED: szString.assign(L"limited war"); break;
+ case WARPLAN_TOTAL: szString.assign(L"total war"); break;
+ case WARPLAN_DOGPILE: szString.assign(L"dogpile war"); break;
+ case NO_WARPLAN: szString.assign(L"unplanned war"); break;
+ default: szString.assign(L"unknown war"); break;
+ }
+}
+
+void CvGameTextMgr::getAttitudeString(CvWStringBuffer& szBuffer, PlayerTypes ePlayer, PlayerTypes eTargetPlayer)
+{
+ CvWString szTempBuffer;
+ int iAttitudeChange;
+ int iPass;
+ int iI;
+ CvPlayerAI& kPlayer = GET_PLAYER(ePlayer);
+ TeamTypes eTeam = (TeamTypes) kPlayer.getTeam();
+ CvTeamAI& kTeam = GET_TEAM(eTeam);
+
+ szBuffer.append(gDLL->getText("TXT_KEY_ATTITUDE_TOWARDS", GC.getAttitudeInfo(GET_PLAYER(ePlayer).AI_getAttitude(eTargetPlayer)).getTextKeyWide(), GET_PLAYER(eTargetPlayer).getNameKey()));
+
+ for (int iTeam = 0; iTeam < MAX_TEAMS; iTeam++)
+ {
+ CvTeam& kLoopTeam = GET_TEAM((TeamTypes)iTeam);
+ if (kLoopTeam.isAlive())
+ {
+ if (NO_PLAYER != eTargetPlayer)
+ {
+ CvTeam& kTargetTeam = GET_TEAM(GET_PLAYER(eTargetPlayer).getTeam());
+ if (kTargetTeam.isHasMet((TeamTypes)iTeam))
+ {
+ if (kTeam.isVassal((TeamTypes)iTeam))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ATTITUDE_VASSAL_OF", kLoopTeam.getName().GetCString()));
+
+ setVassalRevoltHelp(szBuffer, (TeamTypes)iTeam, kTeam.getID());
+ }
+ else if (kLoopTeam.isVassal(kTeam.getID()))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ATTITUDE_MASTER_OF", kLoopTeam.getName().GetCString()));
+ }
+ }
+ }
+ }
+ }
+
+ for (iPass = 0; iPass < 2; iPass++)
+ {
+ iAttitudeChange = kPlayer.AI_getCloseBordersAttitude(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_LAND_TARGET", iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ iAttitudeChange = kPlayer.AI_getWarAttitude(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_WAR", iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ iAttitudeChange = kPlayer.AI_getPeaceAttitude(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_PEACE", iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ iAttitudeChange = kPlayer.AI_getSameReligionAttitude(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_SAME_RELIGION", iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ iAttitudeChange = kPlayer.AI_getDifferentReligionAttitude(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_DIFFERENT_RELIGION", iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ iAttitudeChange = kPlayer.AI_getBonusTradeAttitude(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_BONUS_TRADE", iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ iAttitudeChange = kPlayer.AI_getOpenBordersAttitude(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_OPEN_BORDERS", iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ iAttitudeChange = kPlayer.AI_getDefensivePactAttitude(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_DEFENSIVE_PACT", iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ iAttitudeChange = kPlayer.AI_getRivalDefensivePactAttitude(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_RIVAL_DEFENSIVE_PACT", iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ iAttitudeChange = kPlayer.AI_getRivalVassalAttitude(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_RIVAL_VASSAL", iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ iAttitudeChange = kPlayer.AI_getShareWarAttitude(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_SHARE_WAR", iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ iAttitudeChange = kPlayer.AI_getFavoriteCivicAttitude(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_FAVORITE_CIVIC", iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ iAttitudeChange = kPlayer.AI_getTradeAttitude(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_TRADE", iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ iAttitudeChange = kPlayer.AI_getRivalTradeAttitude(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_RIVAL_TRADE", iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ iAttitudeChange = GET_PLAYER(ePlayer).AI_getColonyAttitude(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_FREEDOM", iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ iAttitudeChange = GET_PLAYER(ePlayer).AI_getAttitudeExtra(eTargetPlayer);
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText(((iAttitudeChange > 0) ? "TXT_KEY_MISC_ATTITUDE_EXTRA_GOOD" : "TXT_KEY_MISC_ATTITUDE_EXTRA_BAD"), iAttitudeChange).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+
+ for (iI = 0; iI < NUM_MEMORY_TYPES; ++iI)
+ {
+ iAttitudeChange = kPlayer.AI_getMemoryAttitude(eTargetPlayer, ((MemoryTypes)iI));
+ if ((iPass == 0) ? (iAttitudeChange > 0) : (iAttitudeChange < 0))
+ {
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR((iAttitudeChange > 0) ? "COLOR_POSITIVE_TEXT" : "COLOR_NEGATIVE_TEXT"), gDLL->getText("TXT_KEY_MISC_ATTITUDE_MEMORY", iAttitudeChange, GC.getMemoryInfo((MemoryTypes)iI).getDescription()).GetCString());
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTempBuffer);
+ }
+ }
+ }
+
+ if (NO_PLAYER != eTargetPlayer)
+ {
+ int iWarWeariness = GET_PLAYER(eTargetPlayer).getModifiedWarWearinessPercentAnger(GET_TEAM(GET_PLAYER(eTargetPlayer).getTeam()).getWarWeariness(eTeam) * std::max(0, 100 + kTeam.getEnemyWarWearinessModifier()));
+ if (iWarWeariness / 10000 > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_WAR_WEAR_HELP", iWarWeariness / 10000));
+ }
+ }
+
+}
+
+void CvGameTextMgr::getEspionageString(CvWStringBuffer& szBuffer, PlayerTypes ePlayer, PlayerTypes eTargetPlayer)
+{
+ if (!GC.getGameINLINE().isOption(GAMEOPTION_NO_ESPIONAGE))
+ {
+ CvPlayer& kPlayer = GET_PLAYER(ePlayer);
+ TeamTypes eTeam = (TeamTypes) kPlayer.getTeam();
+ CvTeam& kTeam = GET_TEAM(eTeam);
+ CvPlayer& kTargetPlayer = GET_PLAYER(eTargetPlayer);
+
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_AGAINST_PLAYER", kTargetPlayer.getNameKey(), kTeam.getEspionagePointsAgainstTeam(kTargetPlayer.getTeam()), GET_TEAM(kTargetPlayer.getTeam()).getEspionagePointsAgainstTeam(kPlayer.getTeam())));
+ }
+}
+
+void CvGameTextMgr::getTradeString(CvWStringBuffer& szBuffer, const TradeData& tradeData, PlayerTypes ePlayer1, PlayerTypes ePlayer2)
+{
+ switch (tradeData.m_eItemType)
+ {
+ case TRADE_GOLD:
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_GOLD", tradeData.m_iData));
+ break;
+ case TRADE_GOLD_PER_TURN:
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_GOLD_PER_TURN", tradeData.m_iData));
+ break;
+ case TRADE_MAPS:
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_WORLD_MAP"));
+ break;
+ case TRADE_SURRENDER:
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_CAPITULATE"));
+ break;
+ case TRADE_VASSAL:
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_VASSAL"));
+ break;
+ case TRADE_OPEN_BORDERS:
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_OPEN_BORDERS"));
+ break;
+ case TRADE_DEFENSIVE_PACT:
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_DEFENSIVE_PACT"));
+ break;
+ case TRADE_PERMANENT_ALLIANCE:
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_PERMANENT_ALLIANCE"));
+ break;
+ case TRADE_PEACE_TREATY:
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_PEACE_TREATY", GC.getDefineINT("PEACE_TREATY_LENGTH")));
+ break;
+ case TRADE_TECHNOLOGIES:
+ szBuffer.assign(CvWString::format(L"%s", GC.getTechInfo((TechTypes)tradeData.m_iData).getDescription()));
+ break;
+ case TRADE_RESOURCES:
+ szBuffer.assign(CvWString::format(L"%s", GC.getBonusInfo((BonusTypes)tradeData.m_iData).getDescription()));
+ break;
+ case TRADE_CITIES:
+ szBuffer.assign(CvWString::format(L"%s", GET_PLAYER(ePlayer1).getCity(tradeData.m_iData)->getName().GetCString()));
+ break;
+ case TRADE_PEACE:
+ case TRADE_WAR:
+ case TRADE_EMBARGO:
+ szBuffer.assign(CvWString::format(L"%s", GET_TEAM((TeamTypes)tradeData.m_iData).getName().GetCString()));
+ break;
+ case TRADE_CIVIC:
+ szBuffer.assign(CvWString::format(L"%s", GC.getCivicInfo((CivicTypes)tradeData.m_iData).getDescription()));
+ break;
+ case TRADE_RELIGION:
+ szBuffer.assign(CvWString::format(L"%s", GC.getReligionInfo((ReligionTypes)tradeData.m_iData).getDescription()));
+ break;
+ default:
+ FAssert(false);
+ break;
+ }
+}
+
+void CvGameTextMgr::setFeatureHelp(CvWStringBuffer &szBuffer, FeatureTypes eFeature, bool bCivilopediaText)
+{
+ if (NO_FEATURE == eFeature)
+ {
+ return;
+ }
+ CvFeatureInfo& feature = GC.getFeatureInfo(eFeature);
+
+ int aiYields[NUM_YIELD_TYPES];
+ if (!bCivilopediaText)
+ {
+ szBuffer.append(feature.getDescription());
+
+ for (int iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ aiYields[iI] = feature.getYieldChange(iI);
+ }
+ setYieldChangeHelp(szBuffer, L"", L"", L"", aiYields);
+ }
+ for (int iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ aiYields[iI] = feature.getRiverYieldChange(iI);
+ }
+ setYieldChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_TERRAIN_NEXT_TO_RIVER"), aiYields);
+
+ for (int iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ aiYields[iI] = feature.getHillsYieldChange(iI);
+ }
+ setYieldChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_TERRAIN_ON_HILLS"), aiYields);
+
+ if (feature.getMovementCost() != 1)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_TERRAIN_MOVEMENT_COST", feature.getMovementCost()));
+ }
+
+ CvWString szHealth;
+ szHealth.Format(L"%.2f", 0.01f * abs(feature.getHealthPercent()));
+ if (feature.getHealthPercent() > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_FEATURE_GOOD_HEALTH", szHealth.GetCString()));
+ }
+ else if (feature.getHealthPercent() < 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_FEATURE_BAD_HEALTH", szHealth.GetCString()));
+ }
+
+ if (feature.getDefenseModifier() != 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_TERRAIN_DEFENSE_MODIFIER", feature.getDefenseModifier()));
+ }
+
+ if (feature.isAddsFreshWater())
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_FEATURE_ADDS_FRESH_WATER"));
+ }
+
+ if (feature.isImpassable())
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_TERRAIN_IMPASSABLE"));
+ }
+
+ if (feature.isNoCity())
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_TERRAIN_NO_CITIES"));
+ }
+
+ if (feature.isNoImprovement())
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_FEATURE_NO_IMPROVEMENT"));
+ }
+
+}
+
+
+void CvGameTextMgr::setTerrainHelp(CvWStringBuffer &szBuffer, TerrainTypes eTerrain, bool bCivilopediaText)
+{
+ if (NO_TERRAIN == eTerrain)
+ {
+ return;
+ }
+ CvTerrainInfo& terrain = GC.getTerrainInfo(eTerrain);
+
+ int aiYields[NUM_YIELD_TYPES];
+ if (!bCivilopediaText)
+ {
+ szBuffer.append(terrain.getDescription());
+
+ for (int iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ aiYields[iI] = terrain.getYield(iI);
+ }
+ setYieldChangeHelp(szBuffer, L"", L"", L"", aiYields);
+ }
+ for (int iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ aiYields[iI] = terrain.getRiverYieldChange(iI);
+ }
+ setYieldChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_TERRAIN_NEXT_TO_RIVER"), aiYields);
+
+ for (int iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ aiYields[iI] = terrain.getHillsYieldChange(iI);
+ }
+ setYieldChangeHelp(szBuffer, L"", L"", gDLL->getText("TXT_KEY_TERRAIN_ON_HILLS"), aiYields);
+
+ if (terrain.getMovementCost() != 1)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_TERRAIN_MOVEMENT_COST", terrain.getMovementCost()));
+ }
+
+ if (terrain.getBuildModifier() != 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_TERRAIN_BUILD_MODIFIER", terrain.getBuildModifier()));
+ }
+
+ if (terrain.getDefenseModifier() != 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_TERRAIN_DEFENSE_MODIFIER", terrain.getDefenseModifier()));
+ }
+
+ if (terrain.isImpassable())
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_TERRAIN_IMPASSABLE"));
+ }
+ if (!terrain.isFound())
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_TERRAIN_NO_CITIES"));
+ bool bFirst = true;
+ if (terrain.isFoundCoast())
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_TERRAIN_COASTAL_CITIES"));
+ bFirst = false;
+ }
+ if (!bFirst)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_OR"));
+ }
+ if (terrain.isFoundFreshWater())
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_TERRAIN_FRESH_WATER_CITIES"));
+ bFirst = false;
+ }
+ }
+}
+
+void CvGameTextMgr::buildFinanceInflationString(CvWStringBuffer& szBuffer, PlayerTypes ePlayer)
+{
+ if (NO_PLAYER == ePlayer)
+ {
+ return;
+ }
+ CvPlayer& kPlayer = GET_PLAYER(ePlayer);
+
+ int iInflationRate = kPlayer.calculateInflationRate();
+ if (iInflationRate != 0)
+ {
+ int iPreInflation = kPlayer.calculatePreInflatedCosts();
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_FINANCE_ADVISOR_INFLATION", iPreInflation, iInflationRate, iInflationRate, iPreInflation, (iPreInflation * iInflationRate) / 100));
+ }
+}
+
+void CvGameTextMgr::buildFinanceUnitCostString(CvWStringBuffer& szBuffer, PlayerTypes ePlayer)
+{
+ if (NO_PLAYER == ePlayer)
+ {
+ return;
+ }
+ CvPlayer& player = GET_PLAYER(ePlayer);
+
+ int iFreeUnits = 0;
+ int iFreeMilitaryUnits = 0;
+ int iUnits = player.getNumUnits();
+ int iMilitaryUnits = player.getNumMilitaryUnits();
+ int iPaidUnits = iUnits;
+ int iPaidMilitaryUnits = iMilitaryUnits;
+ int iMilitaryCost = 0;
+ int iBaseUnitCost = 0;
+ int iExtraCost = 0;
+ int iCost = player.calculateUnitCost(iFreeUnits, iFreeMilitaryUnits, iPaidUnits, iPaidMilitaryUnits, iBaseUnitCost, iMilitaryCost, iExtraCost);
+ int iHandicap = iCost-iBaseUnitCost-iMilitaryCost-iExtraCost;
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_FINANCE_ADVISOR_UNIT_COST", iPaidUnits, iFreeUnits, iBaseUnitCost));
+
+ if (iPaidMilitaryUnits != 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_FINANCE_ADVISOR_UNIT_COST_2", iPaidMilitaryUnits, iFreeMilitaryUnits, iMilitaryCost));
+ }
+ if (iExtraCost != 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_FINANCE_ADVISOR_UNIT_COST_3", iExtraCost));
+ }
+ if (iHandicap != 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_FINANCE_ADVISOR_HANDICAP_COST", iHandicap));
+ }
+ szBuffer.append(gDLL->getText("TXT_KEY_FINANCE_ADVISOR_UNIT_COST_4", iCost));
+}
+
+void CvGameTextMgr::buildFinanceAwaySupplyString(CvWStringBuffer& szBuffer, PlayerTypes ePlayer)
+{
+ if (NO_PLAYER == ePlayer)
+ {
+ return;
+ }
+ CvPlayer& player = GET_PLAYER(ePlayer);
+
+ int iPaidUnits = 0;
+ int iBaseCost = 0;
+ int iCost = player.calculateUnitSupply(iPaidUnits, iBaseCost);
+ int iHandicap = iCost - iBaseCost;
+
+ CvWString szHandicap;
+ if (iHandicap != 0)
+ {
+ szHandicap = gDLL->getText("TXT_KEY_FINANCE_ADVISOR_HANDICAP_COST", iHandicap);
+ }
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_FINANCE_ADVISOR_SUPPLY_COST", iPaidUnits, GC.getDefineINT("INITIAL_FREE_OUTSIDE_UNITS"), iBaseCost, szHandicap.GetCString(), iCost));
+}
+
+void CvGameTextMgr::buildFinanceCityMaintString(CvWStringBuffer& szBuffer, PlayerTypes ePlayer)
+{
+ if (NO_PLAYER == ePlayer)
+ {
+ return;
+ }
+ int iLoop;
+ int iDistanceMaint = 0;
+ int iColonyMaint = 0;
+ int iCorporationMaint = 0;
+
+ CvPlayer& player = GET_PLAYER(ePlayer);
+ for (CvCity* pLoopCity = player.firstCity(&iLoop); pLoopCity != NULL; pLoopCity = player.nextCity(&iLoop))
+ {
+ iDistanceMaint += (pLoopCity->calculateDistanceMaintenanceTimes100() * std::max(0, (pLoopCity->getMaintenanceModifier() + 100))) / 100;
+ iColonyMaint += (pLoopCity->calculateColonyMaintenanceTimes100() * std::max(0, (pLoopCity->getMaintenanceModifier() + 100))) / 100;
+ iCorporationMaint += (pLoopCity->calculateCorporationMaintenanceTimes100() * std::max(0, (pLoopCity->getMaintenanceModifier() + 100))) / 100;
+ }
+ iDistanceMaint /= 100;
+ iColonyMaint /= 100;
+ iCorporationMaint /= 100;
+
+ int iNumCityMaint = player.getTotalMaintenance() - iDistanceMaint - iColonyMaint - iCorporationMaint;
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_FINANCE_ADVISOR_CITY_MAINT_COST", iDistanceMaint, iNumCityMaint, iColonyMaint, iCorporationMaint, player.getTotalMaintenance()));
+}
+
+void CvGameTextMgr::buildFinanceCivicUpkeepString(CvWStringBuffer& szBuffer, PlayerTypes ePlayer)
+{
+ if (NO_PLAYER == ePlayer)
+ {
+ return;
+ }
+ CvPlayer& player = GET_PLAYER(ePlayer);
+ CvWString szCivicOptionCosts;
+ for (int iI = 0; iI < GC.getNumCivicOptionInfos(); ++iI)
+ {
+ CivicTypes eCivic = player.getCivics((CivicOptionTypes)iI);
+ if (NO_CIVIC != eCivic)
+ {
+ CvWString szTemp;
+ szTemp.Format(L"%d%c: %s", player.getSingleCivicUpkeep(eCivic), GC.getCommerceInfo(COMMERCE_GOLD).getChar(), GC.getCivicInfo(eCivic).getDescription());
+ szCivicOptionCosts += NEWLINE + szTemp;
+ }
+ }
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_FINANCE_ADVISOR_CIVIC_UPKEEP_COST", szCivicOptionCosts.GetCString(), player.getCivicUpkeep()));
+}
+
+void CvGameTextMgr::buildFinanceForeignIncomeString(CvWStringBuffer& szBuffer, PlayerTypes ePlayer)
+{
+ if (NO_PLAYER == ePlayer)
+ {
+ return;
+ }
+ CvPlayer& player = GET_PLAYER(ePlayer);
+
+ CvWString szPlayerIncome;
+ for (int iI = 0; iI < MAX_PLAYERS; ++iI)
+ {
+ CvPlayer& otherPlayer = GET_PLAYER((PlayerTypes)iI);
+ if (otherPlayer.isAlive() && player.getGoldPerTurnByPlayer((PlayerTypes)iI) != 0)
+ {
+ CvWString szTemp;
+ szTemp.Format(L"%d%c: %s", player.getGoldPerTurnByPlayer((PlayerTypes)iI), GC.getCommerceInfo(COMMERCE_GOLD).getChar(), otherPlayer.getCivilizationShortDescription());
+ szPlayerIncome += NEWLINE + szTemp;
+ }
+ }
+ if (!szPlayerIncome.empty())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_FINANCE_ADVISOR_FOREIGN_INCOME", szPlayerIncome.GetCString(), player.getGoldPerTurn()));
+ }
+}
+
+void CvGameTextMgr::setProductionHelp(CvWStringBuffer &szBuffer, CvCity& city)
+{
+ FAssertMsg(NO_PLAYER != city.getOwnerINLINE(), "City must have an owner");
+
+ bool bIsProcess = city.isProductionProcess();
+ int iPastOverflow = (bIsProcess ? 0 : city.getOverflowProduction());
+ if (iPastOverflow != 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_OVERFLOW", iPastOverflow));
+ szBuffer.append(NEWLINE);
+ }
+
+ int iFromChops = (city.isProductionProcess() ? 0 : city.getFeatureProduction());
+ if (iFromChops != 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_CHOPS", iFromChops));
+ szBuffer.append(NEWLINE);
+ }
+
+ if (city.getCurrentProductionDifference(false, true) == 0)
+ {
+ return;
+ }
+
+ setYieldHelp(szBuffer, city, YIELD_PRODUCTION);
+
+ int iBaseProduction = city.getBaseYieldRate(YIELD_PRODUCTION) + iPastOverflow + iFromChops;
+ int iBaseModifier = city.getBaseYieldRateModifier(YIELD_PRODUCTION);
+
+ UnitTypes eUnit = city.getProductionUnit();
+ if (NO_UNIT != eUnit)
+ {
+ CvUnitInfo& unit = GC.getUnitInfo(eUnit);
+
+ // Domain
+ int iDomainMod = city.getDomainProductionModifier((DomainTypes)unit.getDomainType());
+ if (0 != iDomainMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_DOMAIN", iDomainMod, GC.getDomainInfo((DomainTypes)unit.getDomainType()).getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iDomainMod;
+ }
+
+ // Military
+ if (unit.isMilitaryProduction())
+ {
+ int iMilitaryMod = city.getMilitaryProductionModifier() + GET_PLAYER(city.getOwnerINLINE()).getMilitaryProductionModifier();
+ if (0 != iMilitaryMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_MILITARY", iMilitaryMod));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iMilitaryMod;
+ }
+ }
+
+ // Bonus
+ for (int i = 0; i < GC.getNumBonusInfos(); i++)
+ {
+ if (city.hasBonus((BonusTypes)i))
+ {
+ int iBonusMod = unit.getBonusProductionModifier(i);
+ if (0 != iBonusMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_MOD_BONUS", iBonusMod, unit.getTextKeyWide(), GC.getBonusInfo((BonusTypes)i).getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iBonusMod;
+ }
+ }
+ }
+
+ // Trait
+ for (int i = 0; i < GC.getNumTraitInfos(); i++)
+ {
+ if (city.hasTrait((TraitTypes)i))
+ {
+ int iTraitMod = unit.getProductionTraits(i);
+
+ if (unit.getSpecialUnitType() != NO_SPECIALUNIT)
+ {
+ iTraitMod += GC.getSpecialUnitInfo((SpecialUnitTypes) unit.getSpecialUnitType()).getProductionTraits(i);
+ }
+ if (0 != iTraitMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_TRAIT", iTraitMod, unit.getTextKeyWide(), GC.getTraitInfo((TraitTypes)i).getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iTraitMod;
+ }
+ }
+ }
+
+ // Religion
+ if (NO_PLAYER != city.getOwnerINLINE() && NO_RELIGION != GET_PLAYER(city.getOwnerINLINE()).getStateReligion())
+ {
+ if (city.isHasReligion(GET_PLAYER(city.getOwnerINLINE()).getStateReligion()))
+ {
+ int iReligionMod = GET_PLAYER(city.getOwnerINLINE()).getStateReligionUnitProductionModifier();
+ if (0 != iReligionMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_RELIGION", iReligionMod, GC.getReligionInfo(GET_PLAYER(city.getOwnerINLINE()).getStateReligion()).getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iReligionMod;
+ }
+ }
+ }
+ }
+
+ BuildingTypes eBuilding = city.getProductionBuilding();
+ if (NO_BUILDING != eBuilding)
+ {
+ CvBuildingInfo& building = GC.getBuildingInfo(eBuilding);
+
+ // Bonus
+ for (int i = 0; i < GC.getNumBonusInfos(); i++)
+ {
+ if (city.hasBonus((BonusTypes)i))
+ {
+ int iBonusMod = building.getBonusProductionModifier(i);
+ if (0 != iBonusMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_MOD_BONUS", iBonusMod, building.getTextKeyWide(), GC.getBonusInfo((BonusTypes)i).getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iBonusMod;
+ }
+ }
+ }
+
+ // Trait
+ for (int i = 0; i < GC.getNumTraitInfos(); i++)
+ {
+ if (city.hasTrait((TraitTypes)i))
+ {
+ int iTraitMod = building.getProductionTraits(i);
+
+ if (building.getSpecialBuildingType() != NO_SPECIALBUILDING)
+ {
+ iTraitMod += GC.getSpecialBuildingInfo((SpecialBuildingTypes) building.getSpecialBuildingType()).getProductionTraits(i);
+ }
+ if (0 != iTraitMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_TRAIT", iTraitMod, building.getTextKeyWide(), GC.getTraitInfo((TraitTypes)i).getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iTraitMod;
+ }
+ }
+ }
+
+ // Wonder
+ if (isWorldWonderClass((BuildingClassTypes)(GC.getBuildingInfo(eBuilding).getBuildingClassType())) && NO_PLAYER != city.getOwnerINLINE())
+ {
+ int iWonderMod = GET_PLAYER(city.getOwnerINLINE()).getMaxGlobalBuildingProductionModifier();
+ if (0 != iWonderMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_WONDER", iWonderMod));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iWonderMod;
+ }
+ }
+
+ // Team Wonder
+ if (isTeamWonderClass((BuildingClassTypes)(GC.getBuildingInfo(eBuilding).getBuildingClassType())) && NO_PLAYER != city.getOwnerINLINE())
+ {
+ int iWonderMod = GET_PLAYER(city.getOwnerINLINE()).getMaxTeamBuildingProductionModifier();
+ if (0 != iWonderMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_TEAM_WONDER", iWonderMod));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iWonderMod;
+ }
+ }
+
+ // National Wonder
+ if (isNationalWonderClass((BuildingClassTypes)(GC.getBuildingInfo(eBuilding).getBuildingClassType())) && NO_PLAYER != city.getOwnerINLINE())
+ {
+ int iWonderMod = GET_PLAYER(city.getOwnerINLINE()).getMaxPlayerBuildingProductionModifier();
+ if (0 != iWonderMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_NATIONAL_WONDER", iWonderMod));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iWonderMod;
+ }
+ }
+
+ // Religion
+ if (NO_PLAYER != city.getOwnerINLINE() && NO_RELIGION != GET_PLAYER(city.getOwnerINLINE()).getStateReligion())
+ {
+ if (city.isHasReligion(GET_PLAYER(city.getOwnerINLINE()).getStateReligion()))
+ {
+ int iReligionMod = GET_PLAYER(city.getOwnerINLINE()).getStateReligionBuildingProductionModifier();
+ if (0 != iReligionMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_RELIGION", iReligionMod, GC.getReligionInfo(GET_PLAYER(city.getOwnerINLINE()).getStateReligion()).getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iReligionMod;
+ }
+ }
+ }
+ }
+
+ ProjectTypes eProject = city.getProductionProject();
+ if (NO_PROJECT != eProject)
+ {
+ CvProjectInfo& project = GC.getProjectInfo(eProject);
+
+ // Spaceship
+ if (project.isSpaceship())
+ {
+ int iSpaceshipMod = city.getSpaceProductionModifier();
+ if (NO_PLAYER != city.getOwnerINLINE())
+ {
+ iSpaceshipMod += GET_PLAYER(city.getOwnerINLINE()).getSpaceProductionModifier();
+ }
+ if (0 != iSpaceshipMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_SPACESHIP", iSpaceshipMod));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iSpaceshipMod;
+ }
+ }
+
+ // Bonus
+ for (int i = 0; i < GC.getNumBonusInfos(); i++)
+ {
+ if (city.hasBonus((BonusTypes)i))
+ {
+ int iBonusMod = project.getBonusProductionModifier(i);
+ if (0 != iBonusMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_MOD_BONUS", iBonusMod, project.getTextKeyWide(), GC.getBonusInfo((BonusTypes)i).getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iBonusMod;
+ }
+ }
+ }
+ }
+
+ int iFoodProduction = (city.isFoodProduction() ? std::max(0, (city.getYieldRate(YIELD_FOOD) - city.foodConsumption(true))) : 0);
+ if (iFoodProduction > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_FOOD", iFoodProduction, iFoodProduction));
+ szBuffer.append(NEWLINE);
+ }
+
+ int iModProduction = iFoodProduction + (iBaseModifier * iBaseProduction) / 100;
+
+ FAssertMsg(iModProduction == city.getCurrentProductionDifference(false, !bIsProcess), "Modified Production does not match actual value");
+
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PROD_FINAL_YIELD", iModProduction));
+ szBuffer.append(NEWLINE);
+
+}
+
+
+void CvGameTextMgr::parsePlayerTraits(CvWStringBuffer &szBuffer, PlayerTypes ePlayer)
+{
+ bool bFirst = true;
+
+ for (int iTrait = 0; iTrait < GC.getNumTraitInfos(); ++iTrait)
+ {
+ if (GET_PLAYER(ePlayer).hasTrait((TraitTypes)iTrait))
+ {
+ if (bFirst)
+ {
+ szBuffer.append(L" (");
+ bFirst = false;
+ }
+ else
+ {
+ szBuffer.append(L", ");
+ }
+ szBuffer.append(GC.getTraitInfo((TraitTypes)iTrait).getDescription());
+ }
+ }
+
+ if (!bFirst)
+ {
+ szBuffer.append(L")");
+ }
+}
+
+void CvGameTextMgr::parseLeaderHeadHelp(CvWStringBuffer &szBuffer, PlayerTypes eThisPlayer, PlayerTypes eOtherPlayer)
+{
+ if (NO_PLAYER == eThisPlayer)
+ {
+ return;
+ }
+
+ szBuffer.append(CvWString::format(L"%s", GET_PLAYER(eThisPlayer).getName()));
+
+ parsePlayerTraits(szBuffer, eThisPlayer);
+
+ szBuffer.append(L"\n");
+
+ if (eOtherPlayer != NO_PLAYER)
+ {
+ CvTeam& kThisTeam = GET_TEAM(GET_PLAYER(eThisPlayer).getTeam());
+ if (eOtherPlayer != eThisPlayer && kThisTeam.isHasMet(GET_PLAYER(eOtherPlayer).getTeam()))
+ {
+ getEspionageString(szBuffer, eThisPlayer, eOtherPlayer);
+
+ getAttitudeString(szBuffer, eThisPlayer, eOtherPlayer);
+
+ getActiveDealsString(szBuffer, eThisPlayer, eOtherPlayer);
+
+ getOtherRelationsString(szBuffer, eThisPlayer, eOtherPlayer);
+ }
+ }
+}
+
+
+void CvGameTextMgr::parseLeaderLineHelp(CvWStringBuffer &szBuffer, PlayerTypes eThisPlayer, PlayerTypes eOtherPlayer)
+{
+ if (NO_PLAYER == eThisPlayer || NO_PLAYER == eOtherPlayer)
+ {
+ return;
+ }
+ CvTeam& thisTeam = GET_TEAM(GET_PLAYER(eThisPlayer).getTeam());
+ CvTeam& otherTeam = GET_TEAM(GET_PLAYER(eOtherPlayer).getTeam());
+
+ if (thisTeam.getID() == otherTeam.getID())
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_PERMANENT_ALLIANCE"));
+ szBuffer.append(NEWLINE);
+ }
+ else if (thisTeam.isAtWar(otherTeam.getID()))
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_CONCEPT_WAR"));
+ szBuffer.append(NEWLINE);
+ }
+ else
+ {
+ if (thisTeam.isDefensivePact(otherTeam.getID()))
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_DEFENSIVE_PACT"));
+ szBuffer.append(NEWLINE);
+ }
+ if (thisTeam.isOpenBorders(otherTeam.getID()))
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_OPEN_BORDERS"));
+ szBuffer.append(NEWLINE);
+ }
+ if (thisTeam.isVassal(otherTeam.getID()))
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_VASSAL"));
+ szBuffer.append(NEWLINE);
+ }
+ }
+}
+
+
+void CvGameTextMgr::getActiveDealsString(CvWStringBuffer &szBuffer, PlayerTypes eThisPlayer, PlayerTypes eOtherPlayer)
+{
+ int iIndex;
+ CvDeal* pDeal = GC.getGameINLINE().firstDeal(&iIndex);
+ while (NULL != pDeal)
+ {
+ if ((pDeal->getFirstPlayer() == eThisPlayer && pDeal->getSecondPlayer() == eOtherPlayer)
+ || (pDeal->getFirstPlayer() == eOtherPlayer && pDeal->getSecondPlayer() == eThisPlayer))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(CvWString::format(L"%c", gDLL->getSymbolID(BULLET_CHAR)));
+ getDealString(szBuffer, *pDeal, eThisPlayer);
+ }
+ pDeal = GC.getGameINLINE().nextDeal(&iIndex);
+ }
+}
+
+void CvGameTextMgr::getOtherRelationsString(CvWStringBuffer& szString, PlayerTypes eThisPlayer, PlayerTypes eOtherPlayer)
+{
+ if (eThisPlayer == NO_PLAYER || eOtherPlayer == NO_PLAYER)
+ {
+ return;
+ }
+ CvPlayer& kThisPlayer = GET_PLAYER(eThisPlayer);
+ CvPlayer& kOtherPlayer = GET_PLAYER(eOtherPlayer);
+
+ for (int iTeam = 0; iTeam < MAX_CIV_TEAMS; ++iTeam)
+ {
+ CvTeamAI& kTeam = GET_TEAM((TeamTypes) iTeam);
+ if (kTeam.isAlive() && !kTeam.isMinorCiv() && iTeam != kThisPlayer.getTeam() && iTeam != kOtherPlayer.getTeam())
+ {
+ if (kTeam.isHasMet(kOtherPlayer.getTeam()))
+ {
+ if (::atWar((TeamTypes) iTeam, kThisPlayer.getTeam()))
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText(L"TXT_KEY_AT_WAR_WITH", kTeam.getName().GetCString()));
+ }
+
+ if (!kTeam.isHuman() && kTeam.AI_getWorstEnemy() == kThisPlayer.getTeam())
+ {
+ szString.append(NEWLINE);
+ szString.append(gDLL->getText(L"TXT_KEY_WORST_ENEMY_OF", kTeam.getName().GetCString()));
+ }
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::buildHintsList(CvWStringBuffer& szBuffer)
+{
+ for (int i = 0; i < GC.getNumHints(); i++)
+ {
+ szBuffer.append(CvWString::format(L"%c%s", gDLL->getSymbolID(BULLET_CHAR), GC.getHints(i).getText()));
+ szBuffer.append(NEWLINE);
+ szBuffer.append(NEWLINE);
+ }
+}
+
+void CvGameTextMgr::setCommerceHelp(CvWStringBuffer &szBuffer, CvCity& city, CommerceTypes eCommerceType)
+{
+ if (NO_COMMERCE == eCommerceType || 0 == city.getCommerceRateTimes100(eCommerceType))
+ {
+ return;
+ }
+ CvCommerceInfo& info = GC.getCommerceInfo(eCommerceType);
+
+ if (NO_PLAYER == city.getOwnerINLINE())
+ {
+ return;
+ }
+ CvPlayer& owner = GET_PLAYER(city.getOwnerINLINE());
+
+ setYieldHelp(szBuffer, city, YIELD_COMMERCE);
+
+ // Slider
+ int iBaseCommerceRate = city.getCommerceFromPercent(eCommerceType, city.getYieldRate(YIELD_COMMERCE) * 100);
+ CvWString szRate = CvWString::format(L"%d.%02d", iBaseCommerceRate/100, iBaseCommerceRate%100);
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_SLIDER_PERCENT_FLOAT", owner.getCommercePercent(eCommerceType), city.getYieldRate(YIELD_COMMERCE), szRate.GetCString(), info.getChar()));
+ szBuffer.append(NEWLINE);
+
+ int iSpecialistCommerce = city.getSpecialistCommerce(eCommerceType) + (city.getSpecialistPopulation() + city.getNumGreatPeople()) * owner.getSpecialistExtraCommerce(eCommerceType);
+ if (0 != iSpecialistCommerce)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_SPECIALIST_COMMERCE", iSpecialistCommerce, info.getChar(), L"TXT_KEY_CONCEPT_SPECIALISTS"));
+ szBuffer.append(NEWLINE);
+ iBaseCommerceRate += 100 * iSpecialistCommerce;
+ }
+
+ int iReligionCommerce = city.getReligionCommerce(eCommerceType);
+ if (0 != iReligionCommerce)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_RELIGION_COMMERCE", iReligionCommerce, info.getChar()));
+ szBuffer.append(NEWLINE);
+ iBaseCommerceRate += 100 * iReligionCommerce;
+ }
+
+ int iCorporationCommerce = city.getCorporationCommerce(eCommerceType);
+ if (0 != iCorporationCommerce)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_CORPORATION_COMMERCE", iCorporationCommerce, info.getChar()));
+ szBuffer.append(NEWLINE);
+ iBaseCommerceRate += 100 * iCorporationCommerce;
+ }
+
+ int iBuildingCommerce = city.getBuildingCommerce(eCommerceType);
+ if (0 != iBuildingCommerce)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_BUILDING_COMMERCE", iBuildingCommerce, info.getChar()));
+ szBuffer.append(NEWLINE);
+ iBaseCommerceRate += 100 * iBuildingCommerce;
+ }
+
+ int iFreeCityCommerce = owner.getFreeCityCommerce(eCommerceType);
+ if (0 != iFreeCityCommerce)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_FREE_CITY_COMMERCE", iFreeCityCommerce, info.getChar()));
+ szBuffer.append(NEWLINE);
+ iBaseCommerceRate += 100 * iFreeCityCommerce;
+ }
+
+
+ FAssertMsg(city.getBaseCommerceRateTimes100(eCommerceType) == iBaseCommerceRate, "Base Commerce rate does not agree with actual value");
+
+ int iModifier = 100;
+
+ // Buildings
+ int iBuildingMod = 0;
+ for (int i = 0; i < GC.getNumBuildingInfos(); i++)
+ {
+ CvBuildingInfo& infoBuilding = GC.getBuildingInfo((BuildingTypes)i);
+ if (city.getNumBuilding((BuildingTypes)i) > 0 && !GET_TEAM(city.getTeam()).isObsoleteBuilding((BuildingTypes)i))
+ {
+ for (int iLoop = 0; iLoop < city.getNumBuilding((BuildingTypes)i); iLoop++)
+ {
+ iBuildingMod += infoBuilding.getCommerceModifier(eCommerceType);
+ // AGDM addition: Add bonus from civics
+ for (int iCivicLoop = 0; iCivicLoop < GC.getNumCivicOptionInfos(); iCivicLoop++) {
+ iBuildingMod += GC.getCivicInfo(owner.getCivics((CivicOptionTypes)iCivicLoop)).getBuildingCommerceModifiers(infoBuilding.getBuildingClassType(), eCommerceType);
+ }
+ }
+ }
+ for (int j = 0; j < MAX_PLAYERS; j++)
+ {
+ if (GET_PLAYER((PlayerTypes)j).isAlive())
+ {
+ if (GET_PLAYER((PlayerTypes)j).getTeam() == owner.getTeam())
+ {
+ int iLoop;
+ for (CvCity* pLoopCity = GET_PLAYER((PlayerTypes)j).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER((PlayerTypes)j).nextCity(&iLoop))
+ {
+ if (pLoopCity->getNumBuilding((BuildingTypes)i) > 0 && !GET_TEAM(pLoopCity->getTeam()).isObsoleteBuilding((BuildingTypes)i))
+ {
+ for (int iLoop = 0; iLoop < pLoopCity->getNumBuilding((BuildingTypes)i); iLoop++)
+ {
+ iBuildingMod += infoBuilding.getGlobalCommerceModifier(eCommerceType);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (0 != iBuildingMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_YIELD_BUILDINGS", iBuildingMod, info.getChar()));
+ szBuffer.append(NEWLINE);
+ iModifier += iBuildingMod;
+ }
+
+
+ // Trait
+ for (int i = 0; i < GC.getNumTraitInfos(); i++)
+ {
+ if (city.hasTrait((TraitTypes)i))
+ {
+ CvTraitInfo& trait = GC.getTraitInfo((TraitTypes)i);
+ int iTraitMod = trait.getCommerceModifier(eCommerceType);
+ if (0 != iTraitMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_COMMERCE_TRAIT", iTraitMod, info.getChar(), trait.getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ iModifier += iTraitMod;
+ }
+ }
+ }
+
+ // Capital
+ int iCapitalMod = city.isCapital() ? owner.getCapitalCommerceRateModifier(eCommerceType) : 0;
+ if (iCapitalMod != 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_YIELD_CAPITAL", iCapitalMod, info.getChar()));
+ szBuffer.append(NEWLINE);
+ iModifier += iCapitalMod;
+ }
+
+
+ // Civics
+ int iCivicMod = 0;
+ for (int i = 0; i < GC.getNumCivicOptionInfos(); i++)
+ {
+ if (NO_CIVIC != owner.getCivics((CivicOptionTypes)i))
+ {
+ iCivicMod += GC.getCivicInfo(owner.getCivics((CivicOptionTypes)i)).getCommerceModifier(eCommerceType);
+ }
+ }
+ if (0 != iCivicMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_YIELD_CIVICS", iCivicMod, info.getChar()));
+ szBuffer.append(NEWLINE);
+ iModifier += iCivicMod;
+ }
+
+ int iModYield = (iModifier * iBaseCommerceRate) / 100;
+
+ int iProductionToCommerce = city.getProductionToCommerceModifier(eCommerceType) * city.getYieldRate(YIELD_PRODUCTION);
+ if (0 != iProductionToCommerce)
+ {
+ if (iProductionToCommerce%100 == 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PRODUCTION_TO_COMMERCE", iProductionToCommerce/100, info.getChar()));
+ szBuffer.append(NEWLINE);
+ }
+ else
+ {
+ szRate = CvWString::format(L"+%d.%02d", iProductionToCommerce/100, iProductionToCommerce%100);
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_PRODUCTION_TO_COMMERCE_FLOAT", szRate.GetCString(), info.getChar()));
+ szBuffer.append(NEWLINE);
+ }
+ iModYield += iProductionToCommerce;
+ }
+
+ if (eCommerceType == COMMERCE_CULTURE && GC.getGameINLINE().isOption(GAMEOPTION_NO_ESPIONAGE))
+ {
+ int iEspionageToCommerce = city.getCommerceRateTimes100(COMMERCE_CULTURE) - iModYield;
+ if (0 != iEspionageToCommerce)
+ {
+ if (iEspionageToCommerce%100 == 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_COMMERCE_TO_COMMERCE", iEspionageToCommerce/100, info.getChar(), GC.getCommerceInfo(COMMERCE_ESPIONAGE).getChar()));
+ szBuffer.append(NEWLINE);
+ }
+ else
+ {
+ szRate = CvWString::format(L"+%d.%02d", iEspionageToCommerce/100, iEspionageToCommerce%100);
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_COMMERCE_TO_COMMERCE_FLOAT", szRate.GetCString(), info.getChar(), GC.getCommerceInfo(COMMERCE_ESPIONAGE).getChar()));
+ szBuffer.append(NEWLINE);
+ }
+ iModYield += iEspionageToCommerce;
+ }
+ }
+
+ FAssertMsg(iModYield == city.getCommerceRateTimes100(eCommerceType), "Commerce yield does not match actual value");
+
+ CvWString szYield = CvWString::format(L"%d.%02d", iModYield/100, iModYield%100);
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_COMMERCE_FINAL_YIELD_FLOAT", info.getTextKeyWide(), szYield.GetCString(), info.getChar()));
+ szBuffer.append(NEWLINE);
+}
+
+void CvGameTextMgr::setYieldHelp(CvWStringBuffer &szBuffer, CvCity& city, YieldTypes eYieldType)
+{
+ FAssertMsg(NO_PLAYER != city.getOwnerINLINE(), "City must have an owner");
+
+ if (NO_YIELD == eYieldType)
+ {
+ return;
+ }
+ CvYieldInfo& info = GC.getYieldInfo(eYieldType);
+
+ if (NO_PLAYER == city.getOwnerINLINE())
+ {
+ return;
+ }
+ CvPlayer& owner = GET_PLAYER(city.getOwnerINLINE());
+
+ int iBaseProduction = city.getBaseYieldRate(eYieldType);
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_BASE_YIELD", info.getTextKeyWide(), iBaseProduction, info.getChar()));
+ szBuffer.append(NEWLINE);
+
+ int iBaseModifier = 100;
+
+ // Buildings
+ int iBuildingMod = 0;
+ for (int i = 0; i < GC.getNumBuildingInfos(); i++)
+ {
+ CvBuildingInfo& infoBuilding = GC.getBuildingInfo((BuildingTypes)i);
+ if (city.getNumBuilding((BuildingTypes)i) > 0 && !GET_TEAM(city.getTeam()).isObsoleteBuilding((BuildingTypes)i))
+ {
+ for (int iLoop = 0; iLoop < city.getNumBuilding((BuildingTypes)i); iLoop++)
+ {
+ iBuildingMod += infoBuilding.getYieldModifier(eYieldType);
+ // AGDM addition: Add bonus from civics
+ for (int iCivicLoop = 0; iCivicLoop < GC.getNumCivicOptionInfos(); iCivicLoop++) {
+ iBuildingMod += GC.getCivicInfo(owner.getCivics((CivicOptionTypes)iCivicLoop)).getBuildingYieldModifiers(infoBuilding.getBuildingClassType(), eYieldType);
+ }
+ }
+ }
+ for (int j = 0; j < MAX_PLAYERS; j++)
+ {
+ if (GET_PLAYER((PlayerTypes)j).isAlive())
+ {
+ if (GET_PLAYER((PlayerTypes)j).getTeam() == owner.getTeam())
+ {
+ int iLoop;
+ for (CvCity* pLoopCity = GET_PLAYER((PlayerTypes)j).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER((PlayerTypes)j).nextCity(&iLoop))
+ {
+ if (pLoopCity->getNumBuilding((BuildingTypes)i) > 0 && !GET_TEAM(pLoopCity->getTeam()).isObsoleteBuilding((BuildingTypes)i))
+ {
+ for (int iLoop = 0; iLoop < pLoopCity->getNumBuilding((BuildingTypes)i); iLoop++)
+ {
+ iBuildingMod += infoBuilding.getGlobalYieldModifier(eYieldType);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (NULL != city.area())
+ {
+ iBuildingMod += city.area()->getYieldRateModifier(city.getOwnerINLINE(), eYieldType);
+ }
+ if (0 != iBuildingMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_YIELD_BUILDINGS", iBuildingMod, info.getChar()));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iBuildingMod;
+ }
+
+ // Power
+ if (city.isPower())
+ {
+ int iPowerMod = city.getPowerYieldRateModifier(eYieldType);
+ if (0 != iPowerMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_YIELD_POWER", iPowerMod, info.getChar()));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iPowerMod;
+ }
+ }
+
+ // Resources
+ int iBonusMod = city.getBonusYieldRateModifier(eYieldType);
+ if (0 != iBonusMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_YIELD_BONUS", iBonusMod, info.getChar()));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iBonusMod;
+ }
+
+ // Capital
+ if (city.isCapital())
+ {
+ int iCapitalMod = owner.getCapitalYieldRateModifier(eYieldType);
+ if (0 != iCapitalMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_YIELD_CAPITAL", iCapitalMod, info.getChar()));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iCapitalMod;
+ }
+ }
+
+ // Civics
+ int iCivicMod = 0;
+ for (int i = 0; i < GC.getNumCivicOptionInfos(); i++)
+ {
+ if (NO_CIVIC != owner.getCivics((CivicOptionTypes)i))
+ {
+ iCivicMod += GC.getCivicInfo(owner.getCivics((CivicOptionTypes)i)).getYieldModifier(eYieldType);
+ }
+ }
+ if (0 != iCivicMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_YIELD_CIVICS", iCivicMod, info.getChar()));
+ szBuffer.append(NEWLINE);
+ iBaseModifier += iCivicMod;
+ }
+
+ FAssertMsg((iBaseModifier * iBaseProduction) / 100 == city.getYieldRate(eYieldType), "Yield Modifier in setProductionHelp does not agree with actual value");
+}
+
+void CvGameTextMgr::setConvertHelp(CvWStringBuffer& szBuffer, PlayerTypes ePlayer, ReligionTypes eReligion)
+{
+ CvWString szReligion = L"TXT_KEY_MISC_NO_STATE_RELIGION";
+
+ if (eReligion != NO_RELIGION)
+ {
+ szReligion = GC.getReligionInfo(eReligion).getTextKeyWide();
+ }
+
+ szBuffer.assign(gDLL->getText("TXT_KEY_MISC_CANNOT_CONVERT_TO", szReligion.GetCString()));
+
+ if (GET_PLAYER(ePlayer).isAnarchy())
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_WHILE_IN_ANARCHY"));
+ }
+ else if (GET_PLAYER(ePlayer).getStateReligion() == eReligion)
+ {
+ szBuffer.append(L". ");
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ALREADY_STATE_REL"));
+ }
+ else if (GET_PLAYER(ePlayer).getConversionTimer() > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ANOTHER_REVOLUTION_RECENTLY"));
+ szBuffer.append(L". ");
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_WAIT_MORE_TURNS", GET_PLAYER(ePlayer).getConversionTimer()));
+ }
+}
+
+void CvGameTextMgr::setRevolutionHelp(CvWStringBuffer& szBuffer, PlayerTypes ePlayer)
+{
+ szBuffer.assign(gDLL->getText("TXT_KEY_MISC_CANNOT_CHANGE_CIVICS"));
+
+ if (GET_PLAYER(ePlayer).isAnarchy())
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_WHILE_IN_ANARCHY"));
+ }
+ else if (GET_PLAYER(ePlayer).getRevolutionTimer() > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_ANOTHER_REVOLUTION_RECENTLY"));
+ szBuffer.append(L" : ");
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_WAIT_MORE_TURNS", GET_PLAYER(ePlayer).getRevolutionTimer()));
+ }
+}
+
+void CvGameTextMgr::setVassalRevoltHelp(CvWStringBuffer& szBuffer, TeamTypes eMaster, TeamTypes eVassal)
+{
+ if (NO_TEAM == eMaster || NO_TEAM == eVassal)
+ {
+ return;
+ }
+
+ if (!GET_TEAM(eVassal).isCapitulated())
+ {
+ return;
+ }
+
+ if (GET_TEAM(eMaster).isParent(eVassal))
+ {
+ return;
+ }
+
+ CvTeam& kMaster = GET_TEAM(eMaster);
+ CvTeam& kVassal = GET_TEAM(eVassal);
+
+ int iMasterLand = kMaster.getTotalLand(false);
+ int iVassalLand = kVassal.getTotalLand(false);
+ if (iMasterLand > 0 && GC.getDefineINT("FREE_VASSAL_LAND_PERCENT") >= 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_VASSAL_LAND_STATS", (iVassalLand * 100) / iMasterLand, GC.getDefineINT("FREE_VASSAL_LAND_PERCENT")));
+ }
+
+ int iMasterPop = kMaster.getTotalPopulation(false);
+ int iVassalPop = kVassal.getTotalPopulation(false);
+ if (iMasterPop > 0 && GC.getDefineINT("FREE_VASSAL_POPULATION_PERCENT") >= 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_VASSAL_POPULATION_STATS", (iVassalPop * 100) / iMasterPop, GC.getDefineINT("FREE_VASSAL_POPULATION_PERCENT")));
+ }
+
+ if (GC.getDefineINT("VASSAL_REVOLT_OWN_LOSSES_FACTOR") > 0 && kVassal.getVassalPower() > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_VASSAL_AREA_LOSS", (iVassalLand * 100) / kVassal.getVassalPower(), GC.getDefineINT("VASSAL_REVOLT_OWN_LOSSES_FACTOR")));
+ }
+
+ if (GC.getDefineINT("VASSAL_REVOLT_MASTER_LOSSES_FACTOR") > 0 && kVassal.getMasterPower() > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_MASTER_AREA_LOSS", (iMasterLand * 100) / kVassal.getMasterPower(), GC.getDefineINT("VASSAL_REVOLT_MASTER_LOSSES_FACTOR")));
+ }
+}
+
+void CvGameTextMgr::parseGreatPeopleHelp(CvWStringBuffer &szBuffer, CvCity& city)
+{
+ int iTotalGreatPeopleUnitProgress;
+ int iI;
+
+ if (NO_PLAYER == city.getOwnerINLINE())
+ {
+ return;
+ }
+ CvPlayer& owner = GET_PLAYER(city.getOwnerINLINE());
+
+ szBuffer.assign(gDLL->getText("TXT_KEY_MISC_GREAT_PERSON", city.getGreatPeopleProgress(), owner.greatPeopleThreshold(false)));
+
+ if (city.getGreatPeopleRate() > 0)
+ {
+ int iGPPLeft = owner.greatPeopleThreshold(false) - city.getGreatPeopleProgress();
+
+ if (iGPPLeft > 0)
+ {
+ int iTurnsLeft = iGPPLeft / city.getGreatPeopleRate();
+
+ if (iTurnsLeft * city.getGreatPeopleRate() < iGPPLeft)
+ {
+ iTurnsLeft++;
+ }
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("INTERFACE_CITY_TURNS", std::max(1, iTurnsLeft)));
+ }
+ }
+
+ iTotalGreatPeopleUnitProgress = 0;
+
+ for (iI = 0; iI < GC.getNumUnitInfos(); ++iI)
+ {
+ iTotalGreatPeopleUnitProgress += city.getGreatPeopleUnitProgress((UnitTypes)iI);
+ }
+
+ if (iTotalGreatPeopleUnitProgress > 0)
+ {
+ szBuffer.append(SEPARATOR);
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_PROB"));
+
+ std::vector< std::pair > aUnitProgress;
+ int iTotalTruncated = 0;
+ for (iI = 0; iI < GC.getNumUnitInfos(); ++iI)
+ {
+ int iProgress = ((city.getGreatPeopleUnitProgress((UnitTypes)iI) * 100) / iTotalGreatPeopleUnitProgress);
+ if (iProgress > 0)
+ {
+ iTotalTruncated += iProgress;
+ aUnitProgress.push_back(std::make_pair((UnitTypes)iI, iProgress));
+ }
+ }
+
+ if (iTotalTruncated < 100 && aUnitProgress.size() > 0)
+ {
+ aUnitProgress[0].second += 100 - iTotalTruncated;
+ }
+
+ for (iI = 0; iI < (int)aUnitProgress.size(); ++iI)
+ {
+ szBuffer.append(CvWString::format(L"%s%s - %d%%", NEWLINE, GC.getUnitInfo(aUnitProgress[iI].first).getDescription(), aUnitProgress[iI].second));
+ }
+ }
+
+ if (city.getGreatPeopleRate() == 0)
+ {
+ return;
+ }
+
+ szBuffer.append(SEPARATOR);
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_GREATPEOPLE_BASE_RATE", city.getBaseGreatPeopleRate()));
+ szBuffer.append(NEWLINE);
+
+ int iModifier = 100;
+
+ // Buildings
+ int iBuildingMod = 0;
+ for (int i = 0; i < GC.getNumBuildingInfos(); i++)
+ {
+ CvBuildingInfo& infoBuilding = GC.getBuildingInfo((BuildingTypes)i);
+ if (city.getNumBuilding((BuildingTypes)i) > 0 && !GET_TEAM(city.getTeam()).isObsoleteBuilding((BuildingTypes)i))
+ {
+ for (int iLoop = 0; iLoop < city.getNumBuilding((BuildingTypes)i); iLoop++)
+ {
+ iBuildingMod += infoBuilding.getGreatPeopleRateModifier();
+ }
+ }
+ for (int j = 0; j < MAX_PLAYERS; j++)
+ {
+ if (GET_PLAYER((PlayerTypes)j).isAlive())
+ {
+ if (GET_PLAYER((PlayerTypes)j).getTeam() == owner.getTeam())
+ {
+ int iLoop;
+ for (CvCity* pLoopCity = GET_PLAYER((PlayerTypes)j).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER((PlayerTypes)j).nextCity(&iLoop))
+ {
+ if (pLoopCity->getNumBuilding((BuildingTypes)i) > 0 && !GET_TEAM(pLoopCity->getTeam()).isObsoleteBuilding((BuildingTypes)i))
+ {
+ for (int iLoop = 0; iLoop < pLoopCity->getNumBuilding((BuildingTypes)i); iLoop++)
+ {
+ iBuildingMod += infoBuilding.getGlobalGreatPeopleRateModifier();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (0 != iBuildingMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_GREATPEOPLE_BUILDINGS", iBuildingMod));
+ szBuffer.append(NEWLINE);
+ iModifier += iBuildingMod;
+ }
+
+ // Civics
+ int iCivicMod = 0;
+ for (int i = 0; i < GC.getNumCivicOptionInfos(); i++)
+ {
+ if (NO_CIVIC != owner.getCivics((CivicOptionTypes)i))
+ {
+ iCivicMod += GC.getCivicInfo(owner.getCivics((CivicOptionTypes)i)).getGreatPeopleRateModifier();
+ if (owner.getStateReligion() != NO_RELIGION && city.isHasReligion(owner.getStateReligion()))
+ {
+ iCivicMod += GC.getCivicInfo(owner.getCivics((CivicOptionTypes)i)).getStateReligionGreatPeopleRateModifier();
+ }
+ }
+ }
+ if (0 != iCivicMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_GREATPEOPLE_CIVICS", iCivicMod));
+ szBuffer.append(NEWLINE);
+ iModifier += iCivicMod;
+ }
+
+ // Trait
+ for (int i = 0; i < GC.getNumTraitInfos(); i++)
+ {
+ if (city.hasTrait((TraitTypes)i))
+ {
+ CvTraitInfo& trait = GC.getTraitInfo((TraitTypes)i);
+ int iTraitMod = trait.getGreatPeopleRateModifier();
+ if (0 != iTraitMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_GREATPEOPLE_TRAIT", iTraitMod, trait.getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ iModifier += iTraitMod;
+ }
+ }
+ }
+
+ if (owner.isGoldenAge())
+ {
+ int iGoldenAgeMod = GC.getDefineINT("GOLDEN_AGE_GREAT_PEOPLE_MODIFIER");
+
+ if (0 != iGoldenAgeMod)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_GREATPEOPLE_GOLDEN_AGE", iGoldenAgeMod));
+ szBuffer.append(NEWLINE);
+ iModifier += iGoldenAgeMod;
+ }
+ }
+
+ int iModGreatPeople = (iModifier * city.getBaseGreatPeopleRate()) / 100;
+
+ FAssertMsg(iModGreatPeople == city.getGreatPeopleRate(), "Great person rate does not match actual value");
+
+ szBuffer.append(gDLL->getText("TXT_KEY_MISC_HELP_GREATPEOPLE_FINAL", iModGreatPeople));
+ szBuffer.append(NEWLINE);
+}
+
+
+void CvGameTextMgr::parseGreatGeneralHelp(CvWStringBuffer &szBuffer, CvPlayer& kPlayer)
+{
+ szBuffer.assign(gDLL->getText("TXT_KEY_MISC_GREAT_GENERAL", kPlayer.getCombatExperience(), kPlayer.greatPeopleThreshold(true)));
+}
+
+
+//------------------------------------------------------------------------------------------------
+
+void CvGameTextMgr::buildCityBillboardIconString( CvWStringBuffer& szBuffer, CvCity* pCity)
+{
+ szBuffer.clear();
+
+ // government center icon
+ if (pCity->isGovernmentCenter() && !(pCity->isCapital()))
+ {
+ szBuffer.append(CvWString::format(L"%c", gDLL->getSymbolID(SILVER_STAR_CHAR)));
+ }
+
+ // happiness, healthiness, superlative icons
+ if (pCity->canBeSelected())
+ {
+ if (pCity->angryPopulation() > 0)
+ {
+ szBuffer.append(CvWString::format(L"%c", gDLL->getSymbolID(UNHAPPY_CHAR)));
+ }
+
+ if (pCity->healthRate() < 0)
+ {
+ szBuffer.append(CvWString::format(L"%c", gDLL->getSymbolID(UNHEALTHY_CHAR)));
+ }
+
+ if (gDLL->getGraphicOption(GRAPHICOPTION_CITY_DETAIL))
+ {
+ if (GET_PLAYER(pCity->getOwnerINLINE()).getNumCities() > 2)
+ {
+ if (pCity->findYieldRateRank(YIELD_PRODUCTION) == 1)
+ {
+ szBuffer.append(CvWString::format(L"%c", GC.getYieldInfo(YIELD_PRODUCTION).getChar()));
+ }
+ if (pCity->findCommerceRateRank(COMMERCE_GOLD) == 1)
+ {
+ szBuffer.append(CvWString::format(L"%c", GC.getCommerceInfo(COMMERCE_GOLD).getChar()));
+ }
+ if (pCity->findCommerceRateRank(COMMERCE_RESEARCH) == 1)
+ {
+ szBuffer.append(CvWString::format(L"%c", GC.getCommerceInfo(COMMERCE_RESEARCH).getChar()));
+ }
+ }
+ }
+
+ if (pCity->isConnectedToCapital())
+ {
+ if (GET_PLAYER(pCity->getOwnerINLINE()).countNumCitiesConnectedToCapital() > 1)
+ {
+ szBuffer.append(CvWString::format(L"%c", gDLL->getSymbolID(TRADE_CHAR)));
+ }
+ }
+ }
+
+ // religion icons
+ for (int iI = 0; iI < GC.getNumReligionInfos(); ++iI)
+ {
+ if (pCity->isHasReligion((ReligionTypes)iI))
+ {
+ if (pCity->isHolyCity((ReligionTypes)iI))
+ {
+ szBuffer.append(CvWString::format(L"%c", GC.getReligionInfo((ReligionTypes) iI).getHolyCityChar()));
+ }
+ else
+ {
+ szBuffer.append(CvWString::format(L"%c", GC.getReligionInfo((ReligionTypes) iI).getChar()));
+ }
+ }
+ }
+
+ // corporation icons
+ for (int iI = 0; iI < GC.getNumCorporationInfos(); ++iI)
+ {
+ if (pCity->isHeadquarters((CorporationTypes)iI))
+ {
+ if (pCity->isHasCorporation((CorporationTypes)iI))
+ {
+ szBuffer.append(CvWString::format(L"%c", GC.getCorporationInfo((CorporationTypes) iI).getHeadquarterChar()));
+ }
+ }
+ else
+ {
+ if (pCity->isActiveCorporation((CorporationTypes)iI))
+ {
+ szBuffer.append(CvWString::format(L"%c", GC.getCorporationInfo((CorporationTypes) iI).getChar()));
+ }
+ }
+ }
+
+ if (pCity->getTeam() == GC.getGameINLINE().getActiveTeam())
+ {
+ if (pCity->isPower())
+ {
+ szBuffer.append(CvWString::format(L"%c", gDLL->getSymbolID(POWER_CHAR)));
+ }
+ }
+
+ // XXX out this in bottom bar???
+ if (pCity->isOccupation())
+ {
+ szBuffer.append(CvWString::format(L" (%c:%d)", gDLL->getSymbolID(OCCUPATION_CHAR), pCity->getOccupationTimer()));
+ }
+
+ // defense icon and text
+ //if (pCity->getTeam() != GC.getGameINLINE().getActiveTeam())
+ {
+ if (pCity->isVisible(GC.getGameINLINE().getActiveTeam(), true))
+ {
+ int iDefenseModifier = pCity->getDefenseModifier(GC.getGameINLINE().selectionListIgnoreBuildingDefense());
+
+ if (iDefenseModifier != 0)
+ {
+ szBuffer.append(CvWString::format(L" %c:%s%d%%", gDLL->getSymbolID(DEFENSE_CHAR), ((iDefenseModifier > 0) ? "+" : ""), iDefenseModifier));
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::buildCityBillboardCityNameString( CvWStringBuffer& szBuffer, CvCity* pCity)
+{
+ szBuffer.assign(pCity->getName());
+
+ if (pCity->canBeSelected())
+ {
+ if (gDLL->getGraphicOption(GRAPHICOPTION_CITY_DETAIL))
+ {
+ if (pCity->foodDifference() > 0)
+ {
+ int iTurns = pCity->getFoodTurnsLeft();
+
+ if ((iTurns > 1) || !(pCity->AI_isEmphasizeAvoidGrowth()))
+ {
+ if (iTurns < MAX_INT)
+ {
+ szBuffer.append(CvWString::format(L" (%d)", iTurns));
+ }
+ }
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::buildCityBillboardProductionString( CvWStringBuffer& szBuffer, CvCity* pCity)
+{
+ if (pCity->getOrderQueueLength() > 0)
+ {
+ szBuffer.assign(pCity->getProductionName());
+
+ if (gDLL->getGraphicOption(GRAPHICOPTION_CITY_DETAIL))
+ {
+ int iTurns = pCity->getProductionTurnsLeft();
+
+ if (iTurns < MAX_INT)
+ {
+ szBuffer.append(CvWString::format(L" (%d)", iTurns));
+ }
+ }
+ }
+ else
+ {
+ szBuffer.clear();
+ }
+}
+
+
+void CvGameTextMgr::buildCityBillboardCitySizeString( CvWStringBuffer& szBuffer, CvCity* pCity, const NiColorA& kColor)
+{
+#define CAPARAMS(c) (int)((c).r * 255.0f), (int)((c).g * 255.0f), (int)((c).b * 255.0f), (int)((c).a * 255.0f)
+ szBuffer.assign(CvWString::format(SETCOLR L"%d" ENDCOLR, CAPARAMS(kColor), pCity->getPopulation()));
+#undef CAPARAMS
+}
+
+void CvGameTextMgr::getCityBillboardFoodbarColors(CvCity* pCity, std::vector& aColors)
+{
+ aColors.resize(NUM_INFOBAR_TYPES);
+ aColors[INFOBAR_STORED] = GC.getColorInfo((ColorTypes)(GC.getYieldInfo(YIELD_FOOD).getColorType())).getColor();
+ aColors[INFOBAR_RATE] = aColors[INFOBAR_STORED];
+ aColors[INFOBAR_RATE].a = 0.5f;
+ aColors[INFOBAR_RATE_EXTRA] = GC.getColorInfo((ColorTypes)GC.getInfoTypeForString("COLOR_NEGATIVE_RATE")).getColor();
+ aColors[INFOBAR_EMPTY] = GC.getColorInfo((ColorTypes)GC.getInfoTypeForString("COLOR_EMPTY")).getColor();
+}
+
+void CvGameTextMgr::getCityBillboardProductionbarColors(CvCity* pCity, std::vector& aColors)
+{
+ aColors.resize(NUM_INFOBAR_TYPES);
+ aColors[INFOBAR_STORED] = GC.getColorInfo((ColorTypes)(GC.getYieldInfo(YIELD_PRODUCTION).getColorType())).getColor();
+ aColors[INFOBAR_RATE] = aColors[INFOBAR_STORED];
+ aColors[INFOBAR_RATE].a = 0.5f;
+ aColors[INFOBAR_RATE_EXTRA] = GC.getColorInfo((ColorTypes)(GC.getYieldInfo(YIELD_FOOD).getColorType())).getColor();
+ aColors[INFOBAR_RATE_EXTRA].a = 0.5f;
+ aColors[INFOBAR_EMPTY] = GC.getColorInfo((ColorTypes)GC.getInfoTypeForString("COLOR_EMPTY")).getColor();
+}
+
+
+void CvGameTextMgr::setScoreHelp(CvWStringBuffer &szString, PlayerTypes ePlayer)
+{
+ if (NO_PLAYER != ePlayer)
+ {
+ CvPlayer& player = GET_PLAYER(ePlayer);
+
+ int iPop = player.getPopScore();
+ int iMaxPop = GC.getGameINLINE().getMaxPopulation();
+ int iPopScore = 0;
+ if (iMaxPop > 0)
+ {
+ iPopScore = (GC.getDefineINT("SCORE_POPULATION_FACTOR") * iPop) / iMaxPop;
+ }
+ int iLand = player.getLandScore();
+ int iMaxLand = GC.getGameINLINE().getMaxLand();
+ int iLandScore = 0;
+ if (iMaxLand > 0)
+ {
+ iLandScore = (GC.getDefineINT("SCORE_LAND_FACTOR") * iLand) / iMaxLand;
+ }
+ int iTech = player.getTechScore();
+ int iMaxTech = GC.getGameINLINE().getMaxTech();
+ int iTechScore = (GC.getDefineINT("SCORE_TECH_FACTOR") * iTech) / iMaxTech;
+ int iWonders = player.getWondersScore();
+ int iMaxWonders = GC.getGameINLINE().getMaxWonders();
+ int iWondersScore = (GC.getDefineINT("SCORE_WONDER_FACTOR") * iWonders) / iMaxWonders;
+ int iTotalScore = iPopScore + iLandScore + iTechScore + iWondersScore;
+ int iVictoryScore = player.calculateScore(true, true);
+ if (iTotalScore == player.calculateScore())
+ {
+ szString.append(gDLL->getText("TXT_KEY_SCORE_BREAKDOWN", iPopScore, iPop, iMaxPop, iLandScore, iLand, iMaxLand, iTechScore, iTech, iMaxTech, iWondersScore, iWonders, iMaxWonders, iTotalScore, iVictoryScore));
+ }
+ }
+}
+
+void CvGameTextMgr::setEventHelp(CvWStringBuffer& szBuffer, EventTypes eEvent, int iEventTriggeredId, PlayerTypes ePlayer)
+{
+ if (NO_EVENT == eEvent || NO_PLAYER == ePlayer)
+ {
+ return;
+ }
+
+ CvEventInfo& kEvent = GC.getEventInfo(eEvent);
+ CvPlayer& kActivePlayer = GET_PLAYER(ePlayer);
+ EventTriggeredData* pTriggeredData = kActivePlayer.getEventTriggered(iEventTriggeredId);
+
+ if (NULL == pTriggeredData)
+ {
+ return;
+ }
+
+ CvCity* pCity = kActivePlayer.getCity(pTriggeredData->m_iCityId);
+ CvCity* pOtherPlayerCity = NULL;
+ CvPlot* pPlot = GC.getMapINLINE().plot(pTriggeredData->m_iPlotX, pTriggeredData->m_iPlotY);
+ CvUnit* pUnit = kActivePlayer.getUnit(pTriggeredData->m_iUnitId);
+
+ if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
+ {
+ pOtherPlayerCity = GET_PLAYER(pTriggeredData->m_eOtherPlayer).getCity(pTriggeredData->m_iOtherPlayerCityId);
+ }
+
+ CvWString szCity = gDLL->getText("TXT_KEY_EVENT_THE_CITY");
+ if (NULL != pCity && kEvent.isCityEffect())
+ {
+ szCity = pCity->getNameKey();
+ }
+ else if (NULL != pOtherPlayerCity && kEvent.isOtherPlayerCityEffect())
+ {
+ szCity = pOtherPlayerCity->getNameKey();
+ }
+
+ CvWString szUnit = gDLL->getText("TXT_KEY_EVENT_THE_UNIT");
+ if (NULL != pUnit)
+ {
+ szUnit = pUnit->getNameKey();
+ }
+
+ CvWString szReligion = gDLL->getText("TXT_KEY_EVENT_THE_RELIGION");
+ if (NO_RELIGION != pTriggeredData->m_eReligion)
+ {
+ szReligion = GC.getReligionInfo(pTriggeredData->m_eReligion).getTextKeyWide();
+ }
+
+ eventGoldHelp(szBuffer, eEvent, ePlayer, pTriggeredData->m_eOtherPlayer);
+
+ eventTechHelp(szBuffer, eEvent, kActivePlayer.getBestEventTech(eEvent, pTriggeredData->m_eOtherPlayer), ePlayer, pTriggeredData->m_eOtherPlayer);
+
+ if (NO_PLAYER != pTriggeredData->m_eOtherPlayer && NO_BONUS != kEvent.getBonusGift())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_GIFT_BONUS_TO_PLAYER", GC.getBonusInfo((BonusTypes)kEvent.getBonusGift()).getTextKeyWide(), GET_PLAYER(pTriggeredData->m_eOtherPlayer).getNameKey()));
+ }
+
+ if (kEvent.getHappy() != 0)
+ {
+ if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
+ {
+ if (kEvent.getHappy() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_HAPPY_FROM_PLAYER", kEvent.getHappy(), kEvent.getHappy(), GET_PLAYER(pTriggeredData->m_eOtherPlayer).getNameKey()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_HAPPY_TO_PLAYER", -kEvent.getHappy(), -kEvent.getHappy(), GET_PLAYER(pTriggeredData->m_eOtherPlayer).getNameKey()));
+ }
+ }
+ else
+ {
+ if (kEvent.getHappy() > 0)
+ {
+ if (kEvent.isCityEffect() || kEvent.isOtherPlayerCityEffect())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_HAPPY_CITY", kEvent.getHappy(), szCity.GetCString()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_HAPPY", kEvent.getHappy()));
+ }
+ }
+ else
+ {
+ if (kEvent.isCityEffect() || kEvent.isOtherPlayerCityEffect())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_UNHAPPY_CITY", -kEvent.getHappy(), szCity.GetCString()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_UNHAPPY", -kEvent.getHappy()));
+ }
+ }
+ }
+ }
+
+ if (kEvent.getHealth() != 0)
+ {
+ if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
+ {
+ if (kEvent.getHealth() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_HEALTH_FROM_PLAYER", kEvent.getHealth(), kEvent.getHealth(), GET_PLAYER(pTriggeredData->m_eOtherPlayer).getNameKey()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_HEALTH_TO_PLAYER", -kEvent.getHealth(), -kEvent.getHealth(), GET_PLAYER(pTriggeredData->m_eOtherPlayer).getNameKey()));
+ }
+ }
+ else
+ {
+ if (kEvent.getHealth() > 0)
+ {
+ if (kEvent.isCityEffect() || kEvent.isOtherPlayerCityEffect())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_HEALTH_CITY", kEvent.getHealth(), szCity.GetCString()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_HEALTH", kEvent.getHealth()));
+ }
+ }
+ else
+ {
+ if (kEvent.isCityEffect() || kEvent.isOtherPlayerCityEffect())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_UNHEALTH", -kEvent.getHealth(), szCity.GetCString()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_UNHEALTH_CITY", -kEvent.getHealth()));
+ }
+ }
+ }
+ }
+
+ if (kEvent.getHurryAnger() != 0)
+ {
+ if (kEvent.isCityEffect() || kEvent.isOtherPlayerCityEffect())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_HURRY_ANGER_CITY", kEvent.getHurryAnger(), szCity.GetCString()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_HURRY_ANGER", kEvent.getHurryAnger()));
+ }
+ }
+
+ if (kEvent.getHappyTurns() > 0)
+ {
+ if (kEvent.isCityEffect() || kEvent.isOtherPlayerCityEffect())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_TEMP_HAPPY_CITY", GC.getDefineINT("TEMP_HAPPY"), kEvent.getHappyTurns(), szCity.GetCString()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_TEMP_HAPPY", GC.getDefineINT("TEMP_HAPPY"), kEvent.getHappyTurns()));
+ }
+ }
+
+ if (kEvent.getFood() != 0)
+ {
+ if (kEvent.isCityEffect() || kEvent.isOtherPlayerCityEffect())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_FOOD_CITY", kEvent.getFood(), szCity.GetCString()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_FOOD", kEvent.getFood()));
+ }
+ }
+
+ if (kEvent.getFoodPercent() != 0)
+ {
+ if (kEvent.isCityEffect() || kEvent.isOtherPlayerCityEffect())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_FOOD_PERCENT_CITY", kEvent.getFoodPercent(), szCity.GetCString()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_FOOD_PERCENT", kEvent.getFoodPercent()));
+ }
+ }
+
+ if (kEvent.getRevoltTurns() > 0)
+ {
+ if (kEvent.isCityEffect() || kEvent.isOtherPlayerCityEffect())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_REVOLT_TURNS", kEvent.getRevoltTurns(), szCity.GetCString()));
+ }
+ }
+
+ if (0 != kEvent.getSpaceProductionModifier())
+ {
+ if (kEvent.isCityEffect() || kEvent.isOtherPlayerCityEffect())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_SPACE_PRODUCTION_CITY", kEvent.getSpaceProductionModifier(), szCity.GetCString()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_SPACESHIP_MOD_ALL_CITIES", kEvent.getSpaceProductionModifier()));
+ }
+ }
+
+ if (kEvent.getMaxPillage() > 0)
+ {
+ if (kEvent.isCityEffect() || kEvent.isOtherPlayerCityEffect())
+ {
+ if (kEvent.getMaxPillage() == kEvent.getMinPillage())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_PILLAGE_CITY", kEvent.getMinPillage(), szCity.GetCString()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_PILLAGE_RANGE_CITY", kEvent.getMinPillage(), kEvent.getMaxPillage(), szCity.GetCString()));
+ }
+ }
+ else
+ {
+ if (kEvent.getMaxPillage() == kEvent.getMinPillage())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_PILLAGE", kEvent.getMinPillage()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_PILLAGE_RANGE", kEvent.getMinPillage(), kEvent.getMaxPillage()));
+ }
+ }
+ }
+
+ for (int i = 0; i < GC.getNumSpecialistInfos(); ++i)
+ {
+ if (kEvent.getFreeSpecialistCount(i) > 0)
+ {
+ if (kEvent.isCityEffect() || kEvent.isOtherPlayerCityEffect())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_FREE_SPECIALIST", kEvent.getFreeSpecialistCount(i), GC.getSpecialistInfo((SpecialistTypes)i).getTextKeyWide(), szCity.GetCString()));
+ }
+ }
+ }
+
+ if (kEvent.getPopulationChange() != 0)
+ {
+ if (kEvent.isCityEffect() || kEvent.isOtherPlayerCityEffect())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_POPULATION_CHANGE_CITY", kEvent.getPopulationChange(), szCity.GetCString()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_POPULATION_CHANGE", kEvent.getPopulationChange()));
+ }
+ }
+
+ if (kEvent.getCulture() != 0)
+ {
+ if (kEvent.isCityEffect() || kEvent.isOtherPlayerCityEffect())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_CULTURE_CITY", kEvent.getCulture(), szCity.GetCString()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_CULTURE", kEvent.getCulture()));
+ }
+ }
+
+ if (kEvent.getUnitClass() != NO_UNITCLASS)
+ {
+ CivilizationTypes eCiv = kActivePlayer.getCivilizationType();
+ if (NO_CIVILIZATION != eCiv)
+ {
+ UnitTypes eUnit = (UnitTypes)GC.getCivilizationInfo(eCiv).getCivilizationUnits(kEvent.getUnitClass());
+ if (eUnit != NO_UNIT)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_BONUS_UNIT", kEvent.getNumUnits(), GC.getUnitInfo(eUnit).getTextKeyWide()));
+ }
+ }
+ }
+
+ if (kEvent.getBuildingClass() != NO_BUILDINGCLASS)
+ {
+ CivilizationTypes eCiv = kActivePlayer.getCivilizationType();
+ if (NO_CIVILIZATION != eCiv)
+ {
+ BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(eCiv).getCivilizationBuildings(kEvent.getBuildingClass());
+ if (eBuilding != NO_BUILDING)
+ {
+ if (kEvent.getBuildingChange() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_BONUS_BUILDING", GC.getBuildingInfo(eBuilding).getTextKeyWide()));
+ }
+ else if (kEvent.getBuildingChange() < 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_REMOVE_BUILDING", GC.getBuildingInfo(eBuilding).getTextKeyWide()));
+ }
+ }
+ }
+ }
+
+ if (kEvent.getNumBuildingYieldChanges() > 0)
+ {
+ CvWStringBuffer szYield;
+ for (int iBuildingClass = 0; iBuildingClass < GC.getNumBuildingClassInfos(); ++iBuildingClass)
+ {
+ CivilizationTypes eCiv = kActivePlayer.getCivilizationType();
+ if (NO_CIVILIZATION != eCiv)
+ {
+ BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(eCiv).getCivilizationBuildings(iBuildingClass);
+ if (eBuilding != NO_BUILDING)
+ {
+ int aiYields[NUM_YIELD_TYPES];
+ for (int iYield = 0; iYield < NUM_YIELD_TYPES; ++iYield)
+ {
+ aiYields[iYield] = kEvent.getBuildingYieldChange(iBuildingClass, iYield);
+ }
+
+ szYield.clear();
+ setYieldChangeHelp(szYield, L"", L"", L"", aiYields, false, false);
+ if (!szYield.isEmpty())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_YIELD_CHANGE_BUILDING", GC.getBuildingInfo(eBuilding).getTextKeyWide(), szYield.getCString()));
+ }
+ }
+ }
+ }
+ }
+
+ if (kEvent.getNumBuildingCommerceChanges() > 0)
+ {
+ CvWStringBuffer szCommerce;
+ for (int iBuildingClass = 0; iBuildingClass < GC.getNumBuildingClassInfos(); ++iBuildingClass)
+ {
+ CivilizationTypes eCiv = kActivePlayer.getCivilizationType();
+ if (NO_CIVILIZATION != eCiv)
+ {
+ BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(eCiv).getCivilizationBuildings(iBuildingClass);
+ if (eBuilding != NO_BUILDING)
+ {
+ int aiCommerces[NUM_COMMERCE_TYPES];
+ for (int iCommerce = 0; iCommerce < NUM_COMMERCE_TYPES; ++iCommerce)
+ {
+ aiCommerces[iCommerce] = kEvent.getBuildingCommerceChange(iBuildingClass, iCommerce);
+ }
+
+ szCommerce.clear();
+ setCommerceChangeHelp(szCommerce, L"", L"", L"", aiCommerces, false, false);
+ if (!szCommerce.isEmpty())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_YIELD_CHANGE_BUILDING", GC.getBuildingInfo(eBuilding).getTextKeyWide(), szCommerce.getCString()));
+ }
+ }
+ }
+ }
+ }
+
+ if (kEvent.getNumBuildingHappyChanges() > 0)
+ {
+ for (int iBuildingClass = 0; iBuildingClass < GC.getNumBuildingClassInfos(); ++iBuildingClass)
+ {
+ CivilizationTypes eCiv = kActivePlayer.getCivilizationType();
+ if (NO_CIVILIZATION != eCiv)
+ {
+ BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(eCiv).getCivilizationBuildings(iBuildingClass);
+ if (eBuilding != NO_BUILDING)
+ {
+ int iHappy = kEvent.getBuildingHappyChange(iBuildingClass);
+ if (iHappy > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_HAPPY_BUILDING", GC.getBuildingInfo(eBuilding).getTextKeyWide(), iHappy, gDLL->getSymbolID(HAPPY_CHAR)));
+ }
+ else if (iHappy < 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_HAPPY_BUILDING", GC.getBuildingInfo(eBuilding).getTextKeyWide(), -iHappy, gDLL->getSymbolID(UNHAPPY_CHAR)));
+ }
+ }
+ }
+ }
+ }
+
+ if (kEvent.getNumBuildingHealthChanges() > 0)
+ {
+ for (int iBuildingClass = 0; iBuildingClass < GC.getNumBuildingClassInfos(); ++iBuildingClass)
+ {
+ CivilizationTypes eCiv = kActivePlayer.getCivilizationType();
+ if (NO_CIVILIZATION != eCiv)
+ {
+ BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(eCiv).getCivilizationBuildings(iBuildingClass);
+ if (eBuilding != NO_BUILDING)
+ {
+ int iHealth = kEvent.getBuildingHealthChange(iBuildingClass);
+ if (iHealth > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_HAPPY_BUILDING", GC.getBuildingInfo(eBuilding).getTextKeyWide(), iHealth, gDLL->getSymbolID(HEALTHY_CHAR)));
+ }
+ else if (iHealth < 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_HAPPY_BUILDING", GC.getBuildingInfo(eBuilding).getTextKeyWide(), -iHealth, gDLL->getSymbolID(UNHEALTHY_CHAR)));
+ }
+ }
+ }
+ }
+ }
+
+ if (kEvent.getFeatureChange() > 0)
+ {
+ if (kEvent.getFeature() != NO_FEATURE)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_FEATURE_GROWTH", GC.getFeatureInfo((FeatureTypes)kEvent.getFeature()).getTextKeyWide()));
+ }
+ }
+ else if (kEvent.getFeatureChange() < 0)
+ {
+ if (NULL != pPlot && NO_FEATURE != pPlot->getFeatureType())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_FEATURE_REMOVE", GC.getFeatureInfo(pPlot->getFeatureType()).getTextKeyWide()));
+ }
+ }
+
+ if (kEvent.getImprovementChange() > 0)
+ {
+ if (kEvent.getImprovement() != NO_IMPROVEMENT)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_IMPROVEMENT_GROWTH", GC.getImprovementInfo((ImprovementTypes)kEvent.getImprovement()).getTextKeyWide()));
+ }
+ }
+ else if (kEvent.getImprovementChange() < 0)
+ {
+ if (NULL != pPlot && NO_IMPROVEMENT != pPlot->getImprovementType())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_IMPROVEMENT_REMOVE", GC.getImprovementInfo(pPlot->getImprovementType()).getTextKeyWide()));
+ }
+ }
+
+ if (kEvent.getBonusChange() > 0)
+ {
+ if (kEvent.getBonus() != NO_BONUS)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_BONUS_GROWTH", GC.getBonusInfo((BonusTypes)kEvent.getBonus()).getTextKeyWide()));
+ }
+ }
+ else if (kEvent.getBonusChange() < 0)
+ {
+ if (NULL != pPlot && NO_BONUS != pPlot->getBonusType())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_BONUS_REMOVE", GC.getBonusInfo(pPlot->getBonusType()).getTextKeyWide()));
+ }
+ }
+
+ if (kEvent.getRouteChange() > 0)
+ {
+ if (kEvent.getRoute() != NO_ROUTE)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_ROUTE_GROWTH", GC.getRouteInfo((RouteTypes)kEvent.getRoute()).getTextKeyWide()));
+ }
+ }
+ else if (kEvent.getRouteChange() < 0)
+ {
+ if (NULL != pPlot && NO_ROUTE != pPlot->getRouteType())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_ROUTE_REMOVE", GC.getRouteInfo(pPlot->getRouteType()).getTextKeyWide()));
+ }
+ }
+
+ int aiYields[NUM_YIELD_TYPES];
+ for (int i = 0; i < NUM_YIELD_TYPES; ++i)
+ {
+ aiYields[i] = kEvent.getPlotExtraYield(i);
+ }
+
+ CvWStringBuffer szYield;
+ setYieldChangeHelp(szYield, L"", L"", L"", aiYields, false, false);
+ if (!szYield.isEmpty())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_YIELD_CHANGE_PLOT", szYield.getCString()));
+ }
+
+ if (NO_BONUS != kEvent.getBonusRevealed())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_BONUS_REVEALED", GC.getBonusInfo((BonusTypes)kEvent.getBonusRevealed()).getTextKeyWide()));
+ }
+
+ if (0 != kEvent.getUnitExperience())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_UNIT_EXPERIENCE", kEvent.getUnitExperience(), szUnit.GetCString()));
+ }
+
+ if (0 != kEvent.isDisbandUnit())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_UNIT_DISBAND", szUnit.GetCString()));
+ }
+
+ if (NO_PROMOTION != kEvent.getUnitPromotion())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_UNIT_PROMOTION", szUnit.GetCString(), GC.getPromotionInfo((PromotionTypes)kEvent.getUnitPromotion()).getTextKeyWide()));
+ }
+
+ for (int i = 0; i < GC.getNumUnitCombatInfos(); ++i)
+ {
+ if (NO_PROMOTION != kEvent.getUnitCombatPromotion(i))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_UNIT_COMBAT_PROMOTION", GC.getUnitCombatInfo((UnitCombatTypes)i).getTextKeyWide(), GC.getPromotionInfo((PromotionTypes)kEvent.getUnitCombatPromotion(i)).getTextKeyWide()));
+ }
+ }
+
+ for (int i = 0; i < GC.getNumUnitClassInfos(); ++i)
+ {
+ if (NO_PROMOTION != kEvent.getUnitClassPromotion(i))
+ {
+ UnitTypes ePromotedUnit = ((UnitTypes)(GC.getCivilizationInfo(kActivePlayer.getCivilizationType()).getCivilizationUnits(i)));
+ if (NO_UNIT != ePromotedUnit)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_UNIT_CLASS_PROMOTION", GC.getUnitInfo(ePromotedUnit).getTextKeyWide(), GC.getPromotionInfo((PromotionTypes)kEvent.getUnitClassPromotion(i)).getTextKeyWide()));
+ }
+ }
+ }
+
+ if (kEvent.getConvertOwnCities() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_CONVERT_OWN_CITIES", kEvent.getConvertOwnCities(), szReligion.GetCString()));
+ }
+
+ if (kEvent.getConvertOtherCities() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_CONVERT_OTHER_CITIES", kEvent.getConvertOtherCities(), szReligion.GetCString()));
+ }
+
+ if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
+ {
+ if (kEvent.getAttitudeModifier() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_ATTITUDE_GOOD", kEvent.getAttitudeModifier(), GET_PLAYER(pTriggeredData->m_eOtherPlayer).getNameKey()));
+ }
+ else if (kEvent.getAttitudeModifier() < 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_ATTITUDE_BAD", kEvent.getAttitudeModifier(), GET_PLAYER(pTriggeredData->m_eOtherPlayer).getNameKey()));
+ }
+ }
+
+ if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
+ {
+ TeamTypes eWorstEnemy = GET_TEAM(GET_PLAYER(pTriggeredData->m_eOtherPlayer).getTeam()).AI_getWorstEnemy();
+ if (NO_TEAM != eWorstEnemy)
+ {
+ if (kEvent.getTheirEnemyAttitudeModifier() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_ATTITUDE_GOOD", kEvent.getTheirEnemyAttitudeModifier(), GET_TEAM(eWorstEnemy).getName().GetCString()));
+ }
+ else if (kEvent.getTheirEnemyAttitudeModifier() < 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_ATTITUDE_BAD", kEvent.getTheirEnemyAttitudeModifier(), GET_TEAM(eWorstEnemy).getName().GetCString()));
+ }
+ }
+ }
+
+ if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
+ {
+ if (kEvent.getEspionagePoints() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_ESPIONAGE_POINTS", kEvent.getEspionagePoints(), GET_PLAYER(pTriggeredData->m_eOtherPlayer).getNameKey()));
+ }
+ else if (kEvent.getEspionagePoints() < 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_ESPIONAGE_COST", -kEvent.getEspionagePoints()));
+ }
+ }
+
+ if (kEvent.isGoldenAge())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_GOLDEN_AGE"));
+ }
+
+ if (0 != kEvent.getFreeUnitSupport())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_FREE_UNIT_SUPPORT", kEvent.getFreeUnitSupport()));
+ }
+
+ if (0 != kEvent.getInflationModifier())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_INFLATION_MODIFIER", kEvent.getInflationModifier()));
+ }
+
+ if (kEvent.isDeclareWar())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_DECLARE_WAR", GET_PLAYER(pTriggeredData->m_eOtherPlayer).getCivilizationAdjectiveKey()));
+ }
+
+ if (kEvent.getUnitImmobileTurns() > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_IMMOBILE_UNIT", kEvent.getUnitImmobileTurns(), szUnit.GetCString()));
+ }
+
+ if (!CvWString(kEvent.getPythonHelp()).empty())
+ {
+ CvWString szHelp;
+ CyArgsList argsList;
+ argsList.add(eEvent);
+ argsList.add(gDLL->getPythonIFace()->makePythonObject(pTriggeredData));
+
+ gDLL->getPythonIFace()->callFunction(PYRandomEventModule, kEvent.getPythonHelp(), argsList.makeFunctionArgs(), &szHelp);
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szHelp);
+ }
+
+ CvWStringBuffer szTemp;
+ for (int i = 0; i < GC.getNumEventInfos(); ++i)
+ {
+ if (0 == kEvent.getAdditionalEventTime(i))
+ {
+ if (kEvent.getAdditionalEventChance(i) > 0)
+ {
+ if (GET_PLAYER(GC.getGameINLINE().getActivePlayer()).canDoEvent((EventTypes)i, *pTriggeredData))
+ {
+ szTemp.clear();
+ setEventHelp(szTemp, (EventTypes)i, iEventTriggeredId, ePlayer);
+
+ if (!szTemp.isEmpty())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_ADDITIONAL_CHANCE", kEvent.getAdditionalEventChance(i), L""));
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTemp);
+ }
+ }
+ }
+ }
+ else
+ {
+ szTemp.clear();
+ setEventHelp(szTemp, (EventTypes)i, iEventTriggeredId, ePlayer);
+
+ if (!szTemp.isEmpty())
+ {
+ CvWString szDelay = gDLL->getText("TXT_KEY_EVENT_DELAY_TURNS", (GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGrowthPercent() * kEvent.getAdditionalEventTime((EventTypes)i)) / 100);
+
+ if (kEvent.getAdditionalEventChance(i) > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_ADDITIONAL_CHANCE", kEvent.getAdditionalEventChance(i), szDelay.GetCString()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_DELAY", szDelay.GetCString()));
+ }
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(szTemp);
+ }
+ }
+ }
+
+ if (NO_TECH != kEvent.getPrereqTech())
+ {
+ if (!GET_TEAM(kActivePlayer.getTeam()).isHasTech((TechTypes)kEvent.getPrereqTech()))
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_REQUIRES_STRING", GC.getTechInfo((TechTypes)(kEvent.getPrereqTech())).getTextKeyWide()));
+ }
+ }
+
+ bool done = false;
+ while(!done)
+ {
+ done = true;
+ if(!szBuffer.isEmpty())
+ {
+ const wchar* wideChar = szBuffer.getCString();
+ if(wideChar[0] == L'\n')
+ {
+ CvWString tempString(&wideChar[1]);
+ szBuffer.clear();
+ szBuffer.append(tempString);
+ done = false;
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::eventTechHelp(CvWStringBuffer& szBuffer, EventTypes eEvent, TechTypes eTech, PlayerTypes eActivePlayer, PlayerTypes eOtherPlayer)
+{
+ CvEventInfo& kEvent = GC.getEventInfo(eEvent);
+
+ if (eTech != NO_TECH)
+ {
+ if (100 == kEvent.getTechPercent())
+ {
+ if (NO_PLAYER != eOtherPlayer)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_TECH_GAINED_FROM_PLAYER", GC.getTechInfo(eTech).getTextKeyWide(), GET_PLAYER(eOtherPlayer).getNameKey()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_TECH_GAINED", GC.getTechInfo(eTech).getTextKeyWide()));
+ }
+ }
+ else if (0 != kEvent.getTechPercent())
+ {
+ CvTeam& kTeam = GET_TEAM(GET_PLAYER(eActivePlayer).getTeam());
+ int iBeakers = (kTeam.getResearchCost(eTech) * kEvent.getTechPercent()) / 100;
+ if (kEvent.getTechPercent() > 0)
+ {
+ iBeakers = std::min(kTeam.getResearchLeft(eTech), iBeakers);
+ }
+ else if (kEvent.getTechPercent() < 0)
+ {
+ iBeakers = std::max(kTeam.getResearchLeft(eTech) - kTeam.getResearchCost(eTech), iBeakers);
+ }
+
+ if (NO_PLAYER != eOtherPlayer)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_TECH_GAINED_FROM_PLAYER_PERCENT", iBeakers, GC.getTechInfo(eTech).getTextKeyWide(), GET_PLAYER(eOtherPlayer).getNameKey()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_TECH_GAINED_PERCENT", iBeakers, GC.getTechInfo(eTech).getTextKeyWide()));
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::eventGoldHelp(CvWStringBuffer& szBuffer, EventTypes eEvent, PlayerTypes ePlayer, PlayerTypes eOtherPlayer)
+{
+ CvEventInfo& kEvent = GC.getEventInfo(eEvent);
+ CvPlayer& kPlayer = GET_PLAYER(ePlayer);
+
+ int iGold1 = kPlayer.getEventCost(eEvent, eOtherPlayer, false);
+ int iGold2 = kPlayer.getEventCost(eEvent, eOtherPlayer, true);
+
+ if (0 != iGold1 || 0 != iGold2)
+ {
+ if (iGold1 == iGold2)
+ {
+ if (NO_PLAYER != eOtherPlayer && kEvent.isGoldToPlayer())
+ {
+ if (iGold1 > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_GOLD_FROM_PLAYER", iGold1, GET_PLAYER(eOtherPlayer).getNameKey()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_GOLD_TO_PLAYER", -iGold1, GET_PLAYER(eOtherPlayer).getNameKey()));
+ }
+ }
+ else
+ {
+ if (iGold1 > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_GOLD_GAINED", iGold1));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_GOLD_LOST", -iGold1));
+ }
+ }
+ }
+ else
+ {
+ if (NO_PLAYER != eOtherPlayer && kEvent.isGoldToPlayer())
+ {
+ if (iGold1 > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_GOLD_RANGE_FROM_PLAYER", iGold1, iGold2, GET_PLAYER(eOtherPlayer).getNameKey()));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_GOLD_RANGE_TO_PLAYER", -iGold1, -iGold2, GET_PLAYER(eOtherPlayer).getNameKey()));
+ }
+ }
+ else
+ {
+ if (iGold1 > 0)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_GOLD_RANGE_GAINED", iGold1, iGold2));
+ }
+ else
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_EVENT_GOLD_RANGE_LOST", -iGold1, iGold2));
+ }
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::setTradeRouteHelp(CvWStringBuffer &szBuffer, int iRoute, CvCity* pCity)
+{
+ if (NULL != pCity)
+ {
+ CvCity* pOtherCity = pCity->getTradeCity(iRoute);
+
+ if (NULL != pOtherCity)
+ {
+ szBuffer.append(pOtherCity->getName());
+
+ int iProfit = pCity->getBaseTradeProfit(pOtherCity);
+
+ szBuffer.append(NEWLINE);
+ CvWString szBaseProfit;
+ szBaseProfit.Format(L"%d.%02d", iProfit/100, iProfit%100);
+ szBuffer.append(gDLL->getText("TXT_KEY_TRADE_ROUTE_HELP_BASE", szBaseProfit.GetCString()));
+
+ int iModifier = 100;
+ int iNewMod;
+
+ for (int iBuilding = 0; iBuilding < GC.getNumBuildingInfos(); ++iBuilding)
+ {
+ if (pCity->getNumActiveBuilding((BuildingTypes)iBuilding) > 0)
+ {
+ iNewMod = pCity->getNumActiveBuilding((BuildingTypes)iBuilding) * GC.getBuildingInfo((BuildingTypes)iBuilding).getTradeRouteModifier();
+ if (0 != iNewMod)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_TRADE_ROUTE_MOD_BUILDING", GC.getBuildingInfo((BuildingTypes)iBuilding).getTextKeyWide(), iNewMod));
+ iModifier += iNewMod;
+ }
+ }
+ }
+
+ iNewMod = pCity->getPopulationTradeModifier();
+ if (0 != iNewMod)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_TRADE_ROUTE_MOD_POPULATION", iNewMod));
+ iModifier += iNewMod;
+ }
+
+ if (pCity->isConnectedToCapital())
+ {
+ iNewMod = GC.getDefineINT("CAPITAL_TRADE_MODIFIER");
+ if (0 != iNewMod)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_TRADE_ROUTE_MOD_CAPITAL", iNewMod));
+ iModifier += iNewMod;
+ }
+ }
+
+ if (NULL != pOtherCity)
+ {
+ if (pCity->area() != pOtherCity->area())
+ {
+ iNewMod = GC.getDefineINT("OVERSEAS_TRADE_MODIFIER");
+ if (0 != iNewMod)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_TRADE_ROUTE_MOD_OVERSEAS", iNewMod));
+ iModifier += iNewMod;
+ }
+ }
+
+ if (pCity->getTeam() != pOtherCity->getTeam())
+ {
+ iNewMod = pCity->getForeignTradeRouteModifier();
+ if (0 != iNewMod)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_TRADE_ROUTE_MOD_FOREIGN", iNewMod));
+ iModifier += iNewMod;
+ }
+
+ iNewMod = pCity->getPeaceTradeModifier(pOtherCity->getTeam());
+ if (0 != iNewMod)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_TRADE_ROUTE_MOD_PEACE", iNewMod));
+ iModifier += iNewMod;
+ }
+ }
+ }
+
+ FAssert(pCity->totalTradeModifier(pOtherCity) == iModifier);
+
+ iProfit *= iModifier;
+ iProfit /= 10000;
+
+ FAssert(iProfit == pCity->calculateTradeProfit(pOtherCity));
+
+ szBuffer.append(SEPARATOR);
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_TRADE_ROUTE_TOTAL", iProfit));
+ }
+ }
+}
+
+void CvGameTextMgr::setEspionageCostHelp(CvWStringBuffer &szBuffer, EspionageMissionTypes eMission, PlayerTypes eTargetPlayer, const CvPlot* pPlot, int iExtraData, const CvUnit* pSpyUnit)
+{
+ CvPlayer& kPlayer = GET_PLAYER(GC.getGameINLINE().getActivePlayer());
+ CvEspionageMissionInfo& kMission = GC.getEspionageMissionInfo(eMission);
+
+ //szBuffer.assign(kMission.getDescription());
+
+ int iMissionCost = kPlayer.getEspionageMissionBaseCost(eMission, eTargetPlayer, pPlot, iExtraData, pSpyUnit);
+
+ if (kMission.isDestroyImprovement())
+ {
+ if (NULL != pPlot && NO_IMPROVEMENT != pPlot->getImprovementType())
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_DESTROY_IMPROVEMENT", GC.getImprovementInfo(pPlot->getImprovementType()).getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ }
+ }
+
+ if (kMission.getDestroyBuildingCostFactor() > 0)
+ {
+ BuildingTypes eTargetBuilding = (BuildingTypes)iExtraData;
+
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+
+ if (NULL != pCity)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_DESTROY_IMPROVEMENT", GC.getBuildingInfo(eTargetBuilding).getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ }
+ }
+ }
+
+ if (kMission.getDestroyProjectCostFactor() > 0)
+ {
+ ProjectTypes eTargetProject = (ProjectTypes)iExtraData;
+
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+
+ if (NULL != pCity)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_DESTROY_IMPROVEMENT", GC.getProjectInfo(eTargetProject).getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ }
+ }
+ }
+
+ if (kMission.getDestroyProductionCostFactor() > 0)
+ {
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+
+ if (NULL != pCity)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_DESTROY_PRODUCTION", pCity->getProduction()));
+ szBuffer.append(NEWLINE);
+ }
+ }
+ }
+
+ if (kMission.getDestroyUnitCostFactor() > 0)
+ {
+ if (NO_PLAYER != eTargetPlayer)
+ {
+ int iTargetUnitID = iExtraData;
+
+ CvUnit* pUnit = GET_PLAYER(eTargetPlayer).getUnit(iTargetUnitID);
+
+ if (NULL != pUnit)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_DESTROY_UNIT", pUnit->getNameKey()));
+ szBuffer.append(NEWLINE);
+ }
+ }
+ }
+
+ if (kMission.getBuyUnitCostFactor() > 0)
+ {
+ if (NO_PLAYER != eTargetPlayer)
+ {
+ int iTargetUnitID = iExtraData;
+
+ CvUnit* pUnit = GET_PLAYER(eTargetPlayer).getUnit(iTargetUnitID);
+
+ if (NULL != pUnit)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_BRIBE", pUnit->getNameKey()));
+ szBuffer.append(NEWLINE);
+ }
+ }
+ }
+
+ if (kMission.getBuyCityCostFactor() > 0)
+ {
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+
+ if (NULL != pCity)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_BRIBE", pCity->getNameKey()));
+ szBuffer.append(NEWLINE);
+ }
+ }
+ }
+
+ if (kMission.getCityInsertCultureCostFactor() > 0)
+ {
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+
+ if (NULL != pCity && pPlot->getCulture(GC.getGameINLINE().getActivePlayer()) > 0)
+ {
+ int iCultureAmount = kMission.getCityInsertCultureAmountFactor() * pCity->countTotalCultureTimes100();
+ iCultureAmount /= 10000;
+ iCultureAmount = std::max(1, iCultureAmount);
+
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_INSERT_CULTURE", pCity->getNameKey(), iCultureAmount, kMission.getCityInsertCultureAmountFactor()));
+ szBuffer.append(NEWLINE);
+ }
+ }
+ }
+
+ if (kMission.getCityPoisonWaterCounter() > 0)
+ {
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+
+ if (NULL != pCity)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_POISON", kMission.getCityPoisonWaterCounter(), gDLL->getSymbolID(UNHEALTHY_CHAR), pCity->getNameKey(), kMission.getCityPoisonWaterCounter()));
+ szBuffer.append(NEWLINE);
+ }
+ }
+ }
+
+ if (kMission.getCityUnhappinessCounter() > 0)
+ {
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+
+ if (NULL != pCity)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_POISON", kMission.getCityUnhappinessCounter(), gDLL->getSymbolID(UNHAPPY_CHAR), pCity->getNameKey(), kMission.getCityUnhappinessCounter()));
+ szBuffer.append(NEWLINE);
+ }
+ }
+ }
+
+ if (kMission.getCityRevoltCounter() > 0)
+ {
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+
+ if (NULL != pCity)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_REVOLT", pCity->getNameKey(), kMission.getCityRevoltCounter()));
+ szBuffer.append(NEWLINE);
+ }
+ }
+ }
+
+ if (kMission.getStealTreasuryTypes() > 0)
+ {
+ if (NO_PLAYER != eTargetPlayer)
+ {
+ int iNumTotalGold = (GET_PLAYER(eTargetPlayer).getGold() * kMission.getStealTreasuryTypes()) / 100;
+
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+
+ if (NULL != pCity)
+ {
+ iNumTotalGold *= pCity->getPopulation();
+ iNumTotalGold /= std::max(1, GET_PLAYER(eTargetPlayer).getTotalPopulation());
+ }
+ }
+
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_STEAL_TREASURY", iNumTotalGold, GET_PLAYER(eTargetPlayer).getCivilizationAdjectiveKey()));
+ szBuffer.append(NEWLINE);
+ }
+ }
+
+ if (kMission.getBuyTechCostFactor() > 0)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_STEAL_TECH", GC.getTechInfo((TechTypes)iExtraData).getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ }
+
+ if (kMission.getSwitchCivicCostFactor() > 0)
+ {
+ if (NO_PLAYER != eTargetPlayer)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_SWITCH_CIVIC", GET_PLAYER(eTargetPlayer).getNameKey(), GC.getCivicInfo((CivicTypes)iExtraData).getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ }
+ }
+
+ if (kMission.getSwitchReligionCostFactor() > 0)
+ {
+ if (NO_PLAYER != eTargetPlayer)
+ {
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_SWITCH_CIVIC", GET_PLAYER(eTargetPlayer).getNameKey(), GC.getReligionInfo((ReligionTypes)iExtraData).getTextKeyWide()));
+ szBuffer.append(NEWLINE);
+ }
+ }
+
+ if (kMission.getPlayerAnarchyCounter() > 0)
+ {
+ if (NO_PLAYER != eTargetPlayer)
+ {
+ int iTurns = (kMission.getPlayerAnarchyCounter() * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getAnarchyPercent()) / 100;
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_ANARCHY", GET_PLAYER(eTargetPlayer).getNameKey(), iTurns));
+ szBuffer.append(NEWLINE);
+ }
+ }
+
+ if (kMission.getCounterespionageNumTurns() > 0 && kMission.getCounterespionageMod() > 0)
+ {
+ if (NO_PLAYER != eTargetPlayer)
+ {
+ int iTurns = (kMission.getCounterespionageNumTurns() * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getResearchPercent()) / 100;
+
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_HELP_COUNTERESPIONAGE", kMission.getCounterespionageMod(), GET_PLAYER(eTargetPlayer).getCivilizationAdjectiveKey(), iTurns));
+ szBuffer.append(NEWLINE);
+ }
+ }
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_BASE_COST", iMissionCost));
+
+ if (kPlayer.getEspionageMissionCost(eMission, eTargetPlayer, pPlot, iExtraData, pSpyUnit) > 0)
+ {
+ int iModifier = 100;
+ int iTempModifier = 0;
+ CvCity* pCity = NULL;
+ if (NULL != pPlot)
+ {
+ pCity = pPlot->getPlotCity();
+ }
+
+ if (pCity != NULL && GC.getEspionageMissionInfo(eMission).isTargetsCity())
+ {
+ // City Population
+ iTempModifier = (GC.getDefineINT("ESPIONAGE_CITY_POP_EACH_MOD") * (pCity->getPopulation() - 1));
+ if (0 != iTempModifier)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_POPULATION_MOD", iTempModifier));
+ iModifier *= 100 + iTempModifier;
+ iModifier /= 100;
+ }
+
+ // Trade Route
+ if (pCity->isTradeRoute(kPlayer.getID()))
+ {
+ iTempModifier = GC.getDefineINT("ESPIONAGE_CITY_TRADE_ROUTE_MOD");
+ if (0 != iTempModifier)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_TRADE_ROUTE_MOD", iTempModifier));
+ iModifier *= 100 + iTempModifier;
+ iModifier /= 100;
+ }
+ }
+
+ ReligionTypes eReligion = kPlayer.getStateReligion();
+ if (NO_RELIGION != eReligion)
+ {
+ iTempModifier = 0;
+
+ if (pCity->isHasReligion(eReligion))
+ {
+ if (GET_PLAYER(eTargetPlayer).getStateReligion() != eReligion)
+ {
+ iTempModifier += GC.getDefineINT("ESPIONAGE_CITY_RELIGION_STATE_MOD");
+ }
+
+ if (kPlayer.hasHolyCity(eReligion))
+ {
+ iTempModifier += GC.getDefineINT("ESPIONAGE_CITY_HOLY_CITY_MOD");;
+ }
+ }
+
+ if (0 != iTempModifier)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_RELIGION_MOD", iTempModifier));
+ iModifier *= 100 + iTempModifier;
+ iModifier /= 100;
+ }
+ }
+
+ // City's culture affects cost
+ iTempModifier = - (pCity->getCultureTimes100(kPlayer.getID()) * GC.getDefineINT("ESPIONAGE_CULTURE_MULTIPLIER_MOD")) / std::max(1, pCity->getCultureTimes100(eTargetPlayer) + pCity->getCultureTimes100(kPlayer.getID()));
+ if (0 != iTempModifier)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_CULTURE_MOD", iTempModifier));
+ iModifier *= 100 + iTempModifier;
+ iModifier /= 100;
+ }
+
+ iTempModifier = pCity->getEspionageDefenseModifier();
+ if (0 != iTempModifier)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_DEFENSE_MOD", iTempModifier));
+ iModifier *= 100 + iTempModifier;
+ iModifier /= 100;
+ }
+ }
+
+ // Distance mod
+ if (pPlot != NULL)
+ {
+ int iDistance = GC.getMap().maxPlotDistance();
+
+ CvCity* pOurCapital = kPlayer.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());
+ }
+ }
+ }
+
+ iTempModifier = (iDistance + GC.getMapINLINE().maxPlotDistance()) * GC.getDefineINT("ESPIONAGE_DISTANCE_MULTIPLIER_MOD") / GC.getMapINLINE().maxPlotDistance() - 100;
+ if (0 != iTempModifier)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_DISTANCE_MOD", iTempModifier));
+ iModifier *= 100 + iTempModifier;
+ iModifier /= 100;
+ }
+ }
+
+ // Spy presence mission cost alteration
+ if (NULL != pSpyUnit)
+ {
+ iTempModifier = -(pSpyUnit->getFortifyTurns() * GC.getDefineINT("ESPIONAGE_EACH_TURN_UNIT_COST_DECREASE"));
+ if (0 != iTempModifier)
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_SPY_STATIONARY_MOD", iTempModifier));
+ iModifier *= 100 + iTempModifier;
+ iModifier /= 100;
+ }
+ }
+
+ // My points VS. Your points to mod cost
+ iTempModifier = ::getEspionageModifier(kPlayer.getTeam(), GET_PLAYER(eTargetPlayer).getTeam()) - 100;
+ if (0 != iTempModifier)
+ {
+ szBuffer.append(SEPARATOR);
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_EP_RATIO_MOD", iTempModifier));
+ iModifier *= 100 + iTempModifier;
+ iModifier /= 100;
+ }
+
+ // Counterespionage Mission Mod
+ CvTeam& kTargetTeam = GET_TEAM(GET_PLAYER(eTargetPlayer).getTeam());
+ if (kTargetTeam.getCounterespionageModAgainstTeam(kPlayer.getTeam()) > 0)
+ {
+ iTempModifier = kTargetTeam.getCounterespionageModAgainstTeam(kPlayer.getTeam()) - 100;
+ if (0 != iTempModifier)
+ {
+ szBuffer.append(SEPARATOR);
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_COUNTERESPIONAGE_MOD", iTempModifier));
+ iModifier *= 100 + iTempModifier;
+ iModifier /= 100;
+ }
+ }
+
+ FAssert(iModifier == kPlayer.getEspionageMissionCostModifier(eMission, eTargetPlayer, pPlot, iExtraData, pSpyUnit));
+
+ iMissionCost *= iModifier;
+ iMissionCost /= 100;
+
+ FAssert(iMissionCost == kPlayer.getEspionageMissionCost(eMission, eTargetPlayer, pPlot, iExtraData, pSpyUnit));
+
+ szBuffer.append(SEPARATOR);
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_COST_TOTAL", iMissionCost));
+
+
+ if (NULL != pSpyUnit)
+ {
+ int iInterceptChance = (pSpyUnit->getSpyInterceptPercent(GET_PLAYER(eTargetPlayer).getTeam()) * (100 + kMission.getDifficultyMod())) / 100;
+
+ szBuffer.append(NEWLINE);
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_CHANCE_OF_SUCCESS", std::min(100, std::max(0, 100 - iInterceptChance))));
+ }
+ }
+}
+
+void CvGameTextMgr::getTradeScreenTitleIcon(CvString& szButton, CvWidgetDataStruct& widgetData, PlayerTypes ePlayer)
+{
+ szButton.clear();
+
+ ReligionTypes eReligion = GET_PLAYER(ePlayer).getStateReligion();
+ if (eReligion != NO_RELIGION)
+ {
+ szButton = GC.getReligionInfo(eReligion).getButton();
+ widgetData.m_eWidgetType = WIDGET_HELP_RELIGION;
+ widgetData.m_iData1 = eReligion;
+ widgetData.m_iData2 = -1;
+ widgetData.m_bOption = false;
+ }
+}
+
+void CvGameTextMgr::getTradeScreenIcons(std::vector< std::pair >& aIconInfos, PlayerTypes ePlayer)
+{
+ aIconInfos.clear();
+ for (int i = 0; i < GC.getNumCivicOptionInfos(); i++)
+ {
+ CivicTypes eCivic = GET_PLAYER(ePlayer).getCivics((CivicOptionTypes)i);
+ CvWidgetDataStruct widgetData;
+ widgetData.m_eWidgetType = WIDGET_PEDIA_JUMP_TO_CIVIC;
+ widgetData.m_iData1 = eCivic;
+ widgetData.m_iData2 = -1;
+ widgetData.m_bOption = false;
+ aIconInfos.push_back(std::make_pair(GC.getCivicInfo(eCivic).getButton(), widgetData));
+ }
+
+}
+
+void CvGameTextMgr::getTradeScreenHeader(CvWString& szHeader, PlayerTypes ePlayer, PlayerTypes eOtherPlayer, bool bAttitude)
+{
+ CvPlayer& kPlayer = GET_PLAYER(ePlayer);
+ szHeader.Format(L"%s - %s", CvWString(kPlayer.getName()).GetCString(), CvWString(kPlayer.getCivilizationDescription()).GetCString());
+ if (bAttitude)
+ {
+ szHeader += CvWString::format(L" (%s)", GC.getAttitudeInfo(kPlayer.AI_getAttitude(eOtherPlayer)).getDescription());
+ }
+}
+
+void CvGameTextMgr::getGlobeLayerName(GlobeLayerTypes eType, int iOption, CvWString& strName)
+{
+ switch (eType)
+ {
+ case GLOBE_LAYER_STRATEGY:
+ switch(iOption)
+ {
+ case 0:
+ strName = gDLL->getText("TXT_KEY_GLOBELAYER_STRATEGY_VIEW");
+ break;
+ case 1:
+ strName = gDLL->getText("TXT_KEY_GLOBELAYER_STRATEGY_NEW_LINE");
+ break;
+ case 2:
+ strName = gDLL->getText("TXT_KEY_GLOBELAYER_STRATEGY_NEW_SIGN");
+ break;
+ case 3:
+ strName = gDLL->getText("TXT_KEY_GLOBELAYER_STRATEGY_DELETE");
+ break;
+ case 4:
+ strName = gDLL->getText("TXT_KEY_GLOBELAYER_STRATEGY_DELETE_LINES");
+ break;
+ }
+ break;
+ case GLOBE_LAYER_UNIT:
+ switch(iOption)
+ {
+ case SHOW_ALL_MILITARY:
+ strName = gDLL->getText("TXT_KEY_GLOBELAYER_UNITS_ALLMILITARY");
+ break;
+ case SHOW_TEAM_MILITARY:
+ strName = gDLL->getText("TXT_KEY_GLOBELAYER_UNITS_TEAMMILITARY");
+ break;
+ case SHOW_ENEMIES_IN_TERRITORY:
+ strName = gDLL->getText("TXT_KEY_GLOBELAYER_UNITS_ENEMY_TERRITORY_MILITARY");
+ break;
+ case SHOW_ENEMIES:
+ strName = gDLL->getText("TXT_KEY_GLOBELAYER_UNITS_ENEMYMILITARY");
+ break;
+ case SHOW_PLAYER_DOMESTICS:
+ strName = gDLL->getText("TXT_KEY_GLOBELAYER_UNITS_DOMESTICS");
+ break;
+ }
+ break;
+ case GLOBE_LAYER_RESOURCE:
+ switch(iOption)
+ {
+ case SHOW_ALL_RESOURCES:
+ strName = gDLL->getText("TXT_KEY_GLOBELAYER_RESOURCES_EVERYTHING");
+ break;
+ case SHOW_STRATEGIC_RESOURCES:
+ strName = gDLL->getText("TXT_KEY_GLOBELAYER_RESOURCES_GENERAL");
+ break;
+ case SHOW_HAPPY_RESOURCES:
+ strName = gDLL->getText("TXT_KEY_GLOBELAYER_RESOURCES_LUXURIES");
+ break;
+ case SHOW_HEALTH_RESOURCES:
+ strName = gDLL->getText("TXT_KEY_GLOBELAYER_RESOURCES_FOOD");
+ break;
+ }
+ break;
+ case GLOBE_LAYER_RELIGION:
+ strName = GC.getReligionInfo((ReligionTypes) iOption).getDescription();
+ break;
+ case GLOBE_LAYER_CULTURE:
+ case GLOBE_LAYER_TRADE:
+ // these have no sub-options
+ strName.clear();
+ break;
+ }
+}
+
+void CvGameTextMgr::getPlotHelp(CvPlot* pMouseOverPlot, CvCity* pCity, CvPlot* pFlagPlot, bool bAlt, CvWStringBuffer& strHelp)
+{
+ if (gDLL->getInterfaceIFace()->isCityScreenUp())
+ {
+ if (pMouseOverPlot != NULL)
+ {
+ CvCity* pHeadSelectedCity = gDLL->getInterfaceIFace()->getHeadSelectedCity();
+ if (pHeadSelectedCity != NULL)
+ {
+ if (pMouseOverPlot->getWorkingCity() == pHeadSelectedCity)
+ {
+ if (pMouseOverPlot->isRevealed(GC.getGameINLINE().getActiveTeam(), true))
+ {
+ setPlotHelp(strHelp, pMouseOverPlot);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (pCity != NULL)
+ {
+ setCityBarHelp(strHelp, pCity);
+ }
+ else if (pFlagPlot != NULL)
+ {
+ setPlotListHelp(strHelp, pFlagPlot, false, true);
+ }
+
+ if (strHelp.isEmpty())
+ {
+ if (pMouseOverPlot != NULL)
+ {
+ if ((pMouseOverPlot == gDLL->getInterfaceIFace()->getGotoPlot()) || bAlt)
+ {
+ if (pMouseOverPlot->isActiveVisible(true))
+ {
+ setCombatPlotHelp(strHelp, pMouseOverPlot);
+ }
+ }
+ }
+ }
+
+ if (strHelp.isEmpty())
+ {
+ if (pMouseOverPlot != NULL)
+ {
+ if (pMouseOverPlot->isRevealed(GC.getGameINLINE().getActiveTeam(), true))
+ {
+ if (pMouseOverPlot->isActiveVisible(true))
+ {
+ setPlotListHelp(strHelp, pMouseOverPlot, true, false);
+
+ if (!strHelp.isEmpty())
+ {
+ strHelp.append(L"\n");
+ }
+ }
+
+ setPlotHelp(strHelp, pMouseOverPlot);
+ }
+ }
+ }
+
+ InterfaceModeTypes eInterfaceMode = gDLL->getInterfaceIFace()->getInterfaceMode();
+ if (eInterfaceMode != INTERFACEMODE_SELECTION)
+ {
+ CvWString szTempBuffer;
+ szTempBuffer.Format(SETCOLR L"%s" ENDCOLR NEWLINE, TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), GC.getInterfaceModeInfo(eInterfaceMode).getDescription());
+
+ switch (eInterfaceMode)
+ {
+ case INTERFACEMODE_REBASE:
+ getRebasePlotHelp(pMouseOverPlot, szTempBuffer);
+ break;
+
+ case INTERFACEMODE_NUKE:
+ getNukePlotHelp(pMouseOverPlot, szTempBuffer);
+ break;
+
+ default:
+ break;
+ }
+
+ szTempBuffer += strHelp.getCString();
+ strHelp.assign(szTempBuffer);
+ }
+ }
+}
+
+void CvGameTextMgr::getRebasePlotHelp(CvPlot* pPlot, CvWString& strHelp)
+{
+ if (NULL != pPlot)
+ {
+ CvUnit* pHeadSelectedUnit = gDLL->getInterfaceIFace()->getHeadSelectedUnit();
+ if (NULL != pHeadSelectedUnit)
+ {
+ if (pPlot->isFriendlyCity(*pHeadSelectedUnit, true))
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+ if (NULL != pCity)
+ {
+ int iNumUnits = pCity->plot()->countNumAirUnits(GC.getGameINLINE().getActiveTeam());
+ bool bFull = (iNumUnits >= pCity->getAirUnitCapacity(GC.getGameINLINE().getActiveTeam()));
+
+ if (bFull)
+ {
+ strHelp += CvWString::format(SETCOLR, TEXT_COLOR("COLOR_WARNING_TEXT"));
+ }
+
+ strHelp += NEWLINE + gDLL->getText("TXT_KEY_CITY_BAR_AIR_UNIT_CAPACITY", iNumUnits, pCity->getAirUnitCapacity(GC.getGameINLINE().getActiveTeam()));
+
+ if (bFull)
+ {
+ strHelp += ENDCOLR;
+ }
+
+ strHelp += NEWLINE;
+ }
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::getNukePlotHelp(CvPlot* pPlot, CvWString& strHelp)
+{
+ if (NULL != pPlot)
+ {
+ CvUnit* pHeadSelectedUnit = gDLL->getInterfaceIFace()->getHeadSelectedUnit();
+
+ if (NULL != pHeadSelectedUnit)
+ {
+ for (int iI = 0; iI < MAX_TEAMS; iI++)
+ {
+ if (pHeadSelectedUnit->isNukeVictim(pPlot, ((TeamTypes)iI)))
+ {
+ if (!pHeadSelectedUnit->isEnemy((TeamTypes)iI))
+ {
+ strHelp += NEWLINE + gDLL->getText("TXT_KEY_CANT_NUKE_FRIENDS");
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::getInterfaceCenterText(CvWString& strText)
+{
+ strText.clear();
+ if (!gDLL->getInterfaceIFace()->isCityScreenUp())
+ {
+ if (GC.getGameINLINE().getWinner() != NO_TEAM)
+ {
+ strText = gDLL->getText("TXT_KEY_MISC_WINS_VICTORY", GET_TEAM(GC.getGameINLINE().getWinner()).getName().GetCString(), GC.getVictoryInfo(GC.getGameINLINE().getVictory()).getTextKeyWide());
+ }
+ else if (!(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).isAlive()))
+ {
+ strText = gDLL->getText("TXT_KEY_MISC_DEFEAT");
+ }
+ }
+}
+
+void CvGameTextMgr::getTurnTimerText(CvWString& strText)
+{
+ strText.clear();
+ if (gDLL->getInterfaceIFace()->getShowInterface() == INTERFACE_SHOW || gDLL->getInterfaceIFace()->getShowInterface() == INTERFACE_ADVANCED_START)
+ {
+ if (GC.getGameINLINE().isMPOption(MPOPTION_TURN_TIMER))
+ {
+ // Get number of turn slices remaining until end-of-turn
+ int iTurnSlicesRemaining = GC.getGameINLINE().getTurnSlicesRemaining();
+
+ if (iTurnSlicesRemaining > 0)
+ {
+ // Get number of seconds remaining
+ int iTurnSecondsRemaining = ((int)floorf((float)(iTurnSlicesRemaining-1) * ((float)gDLL->getMillisecsPerTurn()/1000.0f)) + 1);
+ int iTurnMinutesRemaining = (int)(iTurnSecondsRemaining/60);
+ iTurnSecondsRemaining = (iTurnSecondsRemaining%60);
+ int iTurnHoursRemaining = (int)(iTurnMinutesRemaining/60);
+ iTurnMinutesRemaining = (iTurnMinutesRemaining%60);
+
+ // Display time remaining
+ CvWString szTempBuffer;
+ szTempBuffer.Format(L"%d:%02d:%02d", iTurnHoursRemaining, iTurnMinutesRemaining, iTurnSecondsRemaining);
+ strText += szTempBuffer;
+ }
+ else
+ {
+ // Flash zeroes
+ if (iTurnSlicesRemaining % 2 == 0)
+ {
+ // Display 0
+ strText+=L"0:00";
+ }
+ }
+ }
+
+ if (GC.getGameINLINE().getGameState() == GAMESTATE_ON)
+ {
+ int iMinVictoryTurns = MAX_INT;
+ for (int i = 0; i < GC.getNumVictoryInfos(); ++i)
+ {
+ TeamTypes eActiveTeam = GC.getGameINLINE().getActiveTeam();
+ if (NO_TEAM != eActiveTeam)
+ {
+ int iCountdown = GET_TEAM(eActiveTeam).getVictoryCountdown((VictoryTypes)i);
+ if (iCountdown > 0 && iCountdown < iMinVictoryTurns)
+ {
+ iMinVictoryTurns = iCountdown;
+ }
+ }
+ }
+
+ if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_START) && !GC.getGameINLINE().isOption(GAMEOPTION_ALWAYS_WAR) && GC.getGameINLINE().getElapsedGameTurns() <= GC.getDefineINT("PEACE_TREATY_LENGTH"))
+ {
+ if (!strText.empty())
+ {
+ strText += L" -- ";
+ }
+
+ strText += gDLL->getText("TXT_KEY_MISC_ADVANCED_START_PEACE_REMAINING", GC.getDefineINT("PEACE_TREATY_LENGTH") - GC.getGameINLINE().getElapsedGameTurns());
+ }
+ else if (iMinVictoryTurns < MAX_INT)
+ {
+ if (!strText.empty())
+ {
+ strText += L" -- ";
+ }
+
+ strText += gDLL->getText("TXT_KEY_MISC_TURNS_LEFT_TO_VICTORY", iMinVictoryTurns);
+ }
+ else if (GC.getGameINLINE().getMaxTurns() > 0)
+ {
+ if ((GC.getGameINLINE().getElapsedGameTurns() >= (GC.getGameINLINE().getMaxTurns() - 100)) && (GC.getGameINLINE().getElapsedGameTurns() < GC.getGameINLINE().getMaxTurns()))
+ {
+ if (!strText.empty())
+ {
+ strText += L" -- ";
+ }
+
+ strText += gDLL->getText("TXT_KEY_MISC_TURNS_LEFT", (GC.getGameINLINE().getMaxTurns() - GC.getGameINLINE().getElapsedGameTurns()));
+ }
+ }
+ }
+ }
+}
+
+
+void CvGameTextMgr::getFontSymbols(std::vector< std::vector >& aacSymbols, std::vector& aiMaxNumRows)
+{
+ aacSymbols.push_back(std::vector());
+ aiMaxNumRows.push_back(1);
+ for (int iI = 0; iI < NUM_YIELD_TYPES; iI++)
+ {
+ aacSymbols[aacSymbols.size() - 1].push_back((wchar) GC.getYieldInfo((YieldTypes) iI).getChar());
+ }
+
+ aacSymbols.push_back(std::vector());
+ aiMaxNumRows.push_back(2);
+ for (int iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
+ {
+ aacSymbols[aacSymbols.size() - 1].push_back((wchar) GC.getCommerceInfo((CommerceTypes) iI).getChar());
+ }
+
+ aacSymbols.push_back(std::vector());
+ aiMaxNumRows.push_back(2);
+ for (int iI = 0; iI < GC.getNumReligionInfos(); iI++)
+ {
+ aacSymbols[aacSymbols.size() - 1].push_back((wchar) GC.getReligionInfo((ReligionTypes) iI).getChar());
+ aacSymbols[aacSymbols.size() - 1].push_back((wchar) GC.getReligionInfo((ReligionTypes) iI).getHolyCityChar());
+ }
+ for (int iI = 0; iI < GC.getNumCorporationInfos(); iI++)
+ {
+ aacSymbols[aacSymbols.size() - 1].push_back((wchar) GC.getCorporationInfo((CorporationTypes) iI).getChar());
+ aacSymbols[aacSymbols.size() - 1].push_back((wchar) GC.getCorporationInfo((CorporationTypes) iI).getHeadquarterChar());
+ }
+
+ aacSymbols.push_back(std::vector());
+ aiMaxNumRows.push_back(3);
+ for (int iI = 0; iI < GC.getNumBonusInfos(); iI++)
+ {
+ aacSymbols[aacSymbols.size() - 1].push_back((wchar) GC.getBonusInfo((BonusTypes) iI).getChar());
+ }
+
+ aacSymbols.push_back(std::vector());
+ aiMaxNumRows.push_back(3);
+ for (int iI = 0; iI < MAX_NUM_SYMBOLS; iI++)
+ {
+ aacSymbols[aacSymbols.size() - 1].push_back((wchar) gDLL->getSymbolID(iI));
+ }
+}
+
+void CvGameTextMgr::assignFontIds(int iFirstSymbolCode, int iPadAmount)
+{
+ int iCurSymbolID = iFirstSymbolCode;
+
+ // set yield symbols
+ for (int i = 0; i < NUM_YIELD_TYPES; i++)
+ {
+ GC.getYieldInfo((YieldTypes) i).setChar(iCurSymbolID);
+ ++iCurSymbolID;
+ }
+
+ do
+ {
+ ++iCurSymbolID;
+ } while (iCurSymbolID % iPadAmount != 0);
+
+ // set commerce symbols
+ for (i=0;igetFontButtonIndex();
+ GC.getBonusInfo((BonusTypes) i).setChar(bonusID);
+ ++iCurSymbolID;
+ }
+
+ do
+ {
+ ++iCurSymbolID;
+ } while (iCurSymbolID % iPadAmount != 0);
+
+ if(GC.getNumBonusInfos() < iPadAmount)
+ {
+ do
+ {
+ ++iCurSymbolID;
+ } while (iCurSymbolID % iPadAmount != 0);
+ }
+
+ if(GC.getNumBonusInfos() < 2 * iPadAmount)
+ {
+ do
+ {
+ ++iCurSymbolID;
+ } while (iCurSymbolID % iPadAmount != 0);
+ }
+
+ // set extra symbols
+ for (int i=0; i < MAX_NUM_SYMBOLS; i++)
+ {
+ gDLL->setSymbolID(i, iCurSymbolID);
+ ++iCurSymbolID;
+ }
+}
+
+void CvGameTextMgr::getCityDataForAS(std::vector& mapCityList, std::vector& mapBuildingList, std::vector& mapAutomateList)
+{
+ CvPlayer& kActivePlayer = GET_PLAYER(GC.getGameINLINE().getActivePlayer());
+
+ CvWString szHelp;
+ int iCost = kActivePlayer.getAdvancedStartCityCost(true);
+ if (iCost > 0)
+ {
+ szHelp = gDLL->getText("TXT_KEY_CITY");
+ szHelp += gDLL->getText("TXT_KEY_AS_UNREMOVABLE");
+ mapCityList.push_back(CvWBData(0, szHelp, ARTFILEMGR.getInterfaceArtInfo("INTERFACE_BUTTONS_CITYSELECTION")->getPath()));
+ }
+
+ iCost = kActivePlayer.getAdvancedStartPopCost(true);
+ if (iCost > 0)
+ {
+ szHelp = gDLL->getText("TXT_KEY_WB_AS_POPULATION");
+ mapCityList.push_back(CvWBData(1, szHelp, ARTFILEMGR.getInterfaceArtInfo("INTERFACE_ANGRYCITIZEN_TEXTURE")->getPath()));
+ }
+
+ iCost = kActivePlayer.getAdvancedStartCultureCost(true);
+ if (iCost > 0)
+ {
+ szHelp = gDLL->getText("TXT_KEY_ADVISOR_CULTURE");
+ szHelp += gDLL->getText("TXT_KEY_AS_UNREMOVABLE");
+ mapCityList.push_back(CvWBData(2, szHelp, ARTFILEMGR.getInterfaceArtInfo("CULTURE_BUTTON")->getPath()));
+ }
+
+ CvWStringBuffer szBuffer;
+ for(int i = 0; i < GC.getNumBuildingClassInfos(); i++)
+ {
+ BuildingTypes eBuilding = (BuildingTypes) GC.getCivilizationInfo(kActivePlayer.getCivilizationType()).getCivilizationBuildings(i);
+
+ if (eBuilding != NO_BUILDING)
+ {
+ if (GC.getBuildingInfo(eBuilding).getFreeStartEra() == NO_ERA || GC.getGameINLINE().getStartEra() < GC.getBuildingInfo(eBuilding).getFreeStartEra())
+ {
+ // Building cost -1 denotes unit which may not be purchased
+ iCost = kActivePlayer.getAdvancedStartBuildingCost(eBuilding, true);
+ if (iCost > 0)
+ {
+ szBuffer.clear();
+ setBuildingHelp(szBuffer, eBuilding);
+ mapBuildingList.push_back(CvWBData(eBuilding, szBuffer.getCString(), GC.getBuildingInfo(eBuilding).getButton()));
+ }
+ }
+ }
+ }
+
+ szHelp = gDLL->getText("TXT_KEY_ACTION_AUTOMATE_BUILD");
+ mapAutomateList.push_back(CvWBData(0, szHelp, ARTFILEMGR.getInterfaceArtInfo("INTERFACE_AUTOMATE")->getPath()));
+}
+
+void CvGameTextMgr::getUnitDataForAS(std::vector& mapUnitList)
+{
+ CvPlayer& kActivePlayer = GET_PLAYER(GC.getGameINLINE().getActivePlayer());
+
+ CvWStringBuffer szBuffer;
+ for(int i = 0; i < GC.getNumUnitClassInfos(); i++)
+ {
+ UnitTypes eUnit = (UnitTypes) GC.getCivilizationInfo(kActivePlayer.getCivilizationType()).getCivilizationUnits(i);
+ if (eUnit != NO_UNIT)
+ {
+ // Unit cost -1 denotes unit which may not be purchased
+ int iCost = kActivePlayer.getAdvancedStartUnitCost(eUnit, true);
+ if (iCost > 0)
+ {
+ szBuffer.clear();
+ setUnitHelp(szBuffer, eUnit);
+
+ int iMaxUnitsPerCity = GC.getDefineINT("ADVANCED_START_MAX_UNITS_PER_CITY");
+ if (iMaxUnitsPerCity >= 0 && GC.getUnitInfo(eUnit).isMilitarySupport())
+ {
+ szBuffer.append(NEWLINE);
+ szBuffer.append(gDLL->getText("TXT_KEY_WB_AS_MAX_UNITS_PER_CITY", iMaxUnitsPerCity));
+ }
+ mapUnitList.push_back(CvWBData(eUnit, szBuffer.getCString(), kActivePlayer.getUnitButton(eUnit)));
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::getImprovementDataForAS(std::vector& mapImprovementList, std::vector& mapRouteList)
+{
+ CvPlayer& kActivePlayer = GET_PLAYER(GC.getGameINLINE().getActivePlayer());
+
+ for (int i = 0; i < GC.getNumRouteInfos(); i++)
+ {
+ RouteTypes eRoute = (RouteTypes) i;
+ if (eRoute != NO_ROUTE)
+ {
+ // Route cost -1 denotes route which may not be purchased
+ int iCost = kActivePlayer.getAdvancedStartRouteCost(eRoute, true);
+ if (iCost > 0)
+ {
+ mapRouteList.push_back(CvWBData(eRoute, GC.getRouteInfo(eRoute).getDescription(), GC.getRouteInfo(eRoute).getButton()));
+ }
+ }
+ }
+
+ CvWStringBuffer szBuffer;
+ for (int i = 0; i < GC.getNumImprovementInfos(); i++)
+ {
+ ImprovementTypes eImprovement = (ImprovementTypes) i;
+ if (eImprovement != NO_IMPROVEMENT)
+ {
+ // Improvement cost -1 denotes Improvement which may not be purchased
+ int iCost = kActivePlayer.getAdvancedStartImprovementCost(eImprovement, true);
+ if (iCost > 0)
+ {
+ szBuffer.clear();
+ setImprovementHelp(szBuffer, eImprovement);
+ mapImprovementList.push_back(CvWBData(eImprovement, szBuffer.getCString(), GC.getImprovementInfo(eImprovement).getButton()));
+ }
+ }
+ }
+}
+
+void CvGameTextMgr::getVisibilityDataForAS(std::vector& mapVisibilityList)
+{
+ // Unit cost -1 denotes unit which may not be purchased
+ int iCost = GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getAdvancedStartVisibilityCost(true);
+ if (iCost > 0)
+ {
+ CvWString szHelp = gDLL->getText("TXT_KEY_WB_AS_VISIBILITY");
+ szHelp += gDLL->getText("TXT_KEY_AS_UNREMOVABLE", iCost);
+ mapVisibilityList.push_back(CvWBData(0, szHelp, ARTFILEMGR.getInterfaceArtInfo("INTERFACE_TECH_LOS")->getPath()));
+ }
+}
+
+void CvGameTextMgr::getTechDataForAS(std::vector& mapTechList)
+{
+ mapTechList.push_back(CvWBData(0, gDLL->getText("TXT_KEY_WB_AS_TECH"), ARTFILEMGR.getInterfaceArtInfo("INTERFACE_BTN_TECH")->getPath()));
+}
+
+void CvGameTextMgr::getUnitDataForWB(std::vector& mapUnitData)
+{
+ CvWStringBuffer szBuffer;
+ for (int i = 0; i < GC.getNumUnitInfos(); i++)
+ {
+ szBuffer.clear();
+ setUnitHelp(szBuffer, (UnitTypes)i);
+ mapUnitData.push_back(CvWBData(i, szBuffer.getCString(), GC.getUnitInfo((UnitTypes)i).getButton()));
+ }
+}
+
+void CvGameTextMgr::getBuildingDataForWB(bool bStickyButton, std::vector& mapBuildingData)
+{
+ int iCount = 0;
+ if (!bStickyButton)
+ {
+ mapBuildingData.push_back(CvWBData(iCount++, GC.getMissionInfo(MISSION_FOUND).getDescription(), GC.getMissionInfo(MISSION_FOUND).getButton()));
+ }
+
+ CvWStringBuffer szBuffer;
+ for (int i=0; i < GC.getNumBuildingInfos(); i++)
+ {
+ szBuffer.clear();
+ setBuildingHelp(szBuffer, (BuildingTypes)i);
+ mapBuildingData.push_back(CvWBData(iCount++, szBuffer.getCString(), GC.getBuildingInfo((BuildingTypes)i).getButton()));
+ }
+}
+
+void CvGameTextMgr::getTerrainDataForWB(std::vector& mapTerrainData, std::vector& mapFeatureData, std::vector& mapPlotData, std::vector& mapRouteData)
+{
+ CvWStringBuffer szBuffer;
+
+ for (int i = 0; i < GC.getNumTerrainInfos(); i++)
+ {
+ if (!GC.getTerrainInfo((TerrainTypes)i).isGraphicalOnly())
+ {
+ szBuffer.clear();
+ setTerrainHelp(szBuffer, (TerrainTypes)i);
+ mapTerrainData.push_back(CvWBData(i, szBuffer.getCString(), GC.getTerrainInfo((TerrainTypes)i).getButton()));
+ }
+ }
+
+ for (int i = 0; i < GC.getNumFeatureInfos(); i++)
+ {
+ for (int k = 0; k < GC.getFeatureInfo((FeatureTypes)i).getArtInfo()->getNumVarieties(); k++)
+ {
+ szBuffer.clear();
+ setFeatureHelp(szBuffer, (FeatureTypes)i);
+ mapFeatureData.push_back(CvWBData(i + GC.getNumFeatureInfos() * k, szBuffer.getCString(), GC.getFeatureInfo((FeatureTypes)i).getArtInfo()->getVariety(k).getVarietyButton()));
+ }
+ }
+
+ mapPlotData.push_back(CvWBData(0, gDLL->getText("TXT_KEY_WB_PLOT_TYPE_MOUNTAIN"), ARTFILEMGR.getInterfaceArtInfo("WORLDBUILDER_PLOT_TYPE_MOUNTAIN")->getPath()));
+ mapPlotData.push_back(CvWBData(1, gDLL->getText("TXT_KEY_WB_PLOT_TYPE_HILL"), ARTFILEMGR.getInterfaceArtInfo("WORLDBUILDER_PLOT_TYPE_HILL")->getPath()));
+ mapPlotData.push_back(CvWBData(2, gDLL->getText("TXT_KEY_WB_PLOT_TYPE_PLAINS"), ARTFILEMGR.getInterfaceArtInfo("WORLDBUILDER_PLOT_TYPE_PLAINS")->getPath()));
+ mapPlotData.push_back(CvWBData(3, gDLL->getText("TXT_KEY_WB_PLOT_TYPE_OCEAN"), ARTFILEMGR.getInterfaceArtInfo("WORLDBUILDER_PLOT_TYPE_OCEAN")->getPath()));
+
+ for (int i = 0; i < GC.getNumRouteInfos(); i++)
+ {
+ mapRouteData.push_back(CvWBData(i, GC.getRouteInfo((RouteTypes)i).getDescription(), GC.getRouteInfo((RouteTypes)i).getButton()));
+ }
+ mapRouteData.push_back(CvWBData(GC.getNumRouteInfos(), gDLL->getText("TXT_KEY_WB_RIVER_PLACEMENT"), ARTFILEMGR.getInterfaceArtInfo("WORLDBUILDER_RIVER_PLACEMENT")->getPath()));
+}
+
+void CvGameTextMgr::getTerritoryDataForWB(std::vector& mapTerritoryData)
+{
+ for (int i = 0; i <= MAX_CIV_PLAYERS; i++)
+ {
+ CvWString szName = gDLL->getText("TXT_KEY_MAIN_MENU_NONE");
+ CvString szButton = GC.getCivilizationInfo(GET_PLAYER(BARBARIAN_PLAYER).getCivilizationType()).getButton();
+
+ if (GET_PLAYER((PlayerTypes) i).isEverAlive())
+ {
+ szName = GET_PLAYER((PlayerTypes)i).getName();
+ szButton = GC.getCivilizationInfo(GET_PLAYER((PlayerTypes)i).getCivilizationType()).getButton();
+ }
+ mapTerritoryData.push_back(CvWBData(i, szName, szButton));
+ }
+}
+
+
+void CvGameTextMgr::getTechDataForWB(std::vector& mapTechData)
+{
+ CvWStringBuffer szBuffer;
+ for (int i=0; i < GC.getNumTechInfos(); i++)
+ {
+ szBuffer.clear();
+ setTechHelp(szBuffer, (TechTypes) i);
+ mapTechData.push_back(CvWBData(i, szBuffer.getCString(), GC.getTechInfo((TechTypes) i).getButton()));
+ }
+}
+
+void CvGameTextMgr::getPromotionDataForWB(std::vector& mapPromotionData)
+{
+ CvWStringBuffer szBuffer;
+ for (int i=0; i < GC.getNumPromotionInfos(); i++)
+ {
+ szBuffer.clear();
+ setPromotionHelp(szBuffer, (PromotionTypes) i, false);
+ mapPromotionData.push_back(CvWBData(i, szBuffer.getCString(), GC.getPromotionInfo((PromotionTypes) i).getButton()));
+ }
+}
+
+void CvGameTextMgr::getBonusDataForWB(std::vector& mapBonusData)
+{
+ CvWStringBuffer szBuffer;
+ for (int i=0; i < GC.getNumBonusInfos(); i++)
+ {
+ szBuffer.clear();
+ setBonusHelp(szBuffer, (BonusTypes)i);
+ mapBonusData.push_back(CvWBData(i, szBuffer.getCString(), GC.getBonusInfo((BonusTypes) i).getButton()));
+ }
+}
+
+void CvGameTextMgr::getImprovementDataForWB(std::vector& mapImprovementData)
+{
+ CvWStringBuffer szBuffer;
+ for (int i=0; i < GC.getNumImprovementInfos(); i++)
+ {
+ CvImprovementInfo& kInfo = GC.getImprovementInfo((ImprovementTypes) i);
+ if (!kInfo.isGraphicalOnly())
+ {
+ szBuffer.clear();
+ setImprovementHelp(szBuffer, (ImprovementTypes) i);
+ mapImprovementData.push_back(CvWBData(i, szBuffer.getCString(), kInfo.getButton()));
+ }
+ }
+}
+
+void CvGameTextMgr::getReligionDataForWB(bool bHolyCity, std::vector& mapReligionData)
+{
+ for (int i = 0; i < GC.getNumReligionInfos(); ++i)
+ {
+ CvReligionInfo& kInfo = GC.getReligionInfo((ReligionTypes) i);
+ CvWString strDescription = kInfo.getDescription();
+ if (bHolyCity)
+ {
+ strDescription = gDLL->getText("TXT_KEY_WB_HOLYCITY", strDescription.GetCString());
+ }
+ mapReligionData.push_back(CvWBData(i, strDescription, kInfo.getButton()));
+ }
+}
+
+
+void CvGameTextMgr::getCorporationDataForWB(bool bHeadquarters, std::vector& mapCorporationData)
+{
+ for (int i = 0; i < GC.getNumCorporationInfos(); ++i)
+ {
+ CvCorporationInfo& kInfo = GC.getCorporationInfo((CorporationTypes) i);
+ CvWString strDescription = kInfo.getDescription();
+ if (bHeadquarters)
+ {
+ strDescription = gDLL->getText("TXT_KEY_CORPORATION_HEADQUARTERS", strDescription.GetCString());
+ }
+ mapCorporationData.push_back(CvWBData(i, strDescription, kInfo.getButton()));
+ }
+}
diff --git a/CvGameCoreDLL/CvInfos.cpp b/CvGameCoreDLL/CvInfos.cpp
index ae02b9f..b8eaec4 100644
--- a/CvGameCoreDLL/CvInfos.cpp
+++ b/CvGameCoreDLL/CvInfos.cpp
@@ -5303,8 +5303,18 @@ m_piCommerceModifier(NULL),
m_piCapitalCommerceModifier(NULL),
m_piSpecialistExtraCommerce(NULL),
m_paiBuildingHappinessChanges(NULL),
+m_paiRtRExtraSpecialistCounts(NULL), //Plako for RtR mod 21.7.2015
m_paiBuildingHealthChanges(NULL),
m_paiFeatureHappinessChanges(NULL),
+
+m_ppiBuildingYieldChanges(NULL), // AGDM addition
+m_ppiBuildingYieldModifiers(NULL), // AGDM addition
+m_ppiBuildingCommerceChanges(NULL), // AGDM addition
+m_ppiBuildingCommerceModifiers(NULL), // AGDM addition
+m_ppiBuildingFreeSpecialistCounts(NULL), // AGDM addition
+m_paiBuildingMilitaryProductionModifiers(NULL), // AGDM addition
+m_paiBuildingFreeExperiences(NULL), // AGDM addition
+
m_pabHurry(NULL),
m_pabSpecialBuildingNotRequired(NULL),
m_pabSpecialistValid(NULL),
@@ -5330,8 +5340,18 @@ CvCivicInfo::~CvCivicInfo()
SAFE_DELETE_ARRAY(m_piCapitalCommerceModifier);
SAFE_DELETE_ARRAY(m_piSpecialistExtraCommerce);
SAFE_DELETE_ARRAY(m_paiBuildingHappinessChanges);
+ SAFE_DELETE_ARRAY(m_paiRtRExtraSpecialistCounts); //Plako for RtR mod 22.7.2015
SAFE_DELETE_ARRAY(m_paiBuildingHealthChanges);
SAFE_DELETE_ARRAY(m_paiFeatureHappinessChanges);
+
+ this->delete2DimArray(m_ppiBuildingYieldChanges, GC.getNumBuildingClassInfos()); // AGDM addition
+ this->delete2DimArray(m_ppiBuildingYieldModifiers, GC.getNumBuildingClassInfos()); // AGDM addition
+ this->delete2DimArray(m_ppiBuildingCommerceChanges, GC.getNumBuildingClassInfos()); // AGDM addition
+ this->delete2DimArray(m_ppiBuildingCommerceModifiers, GC.getNumBuildingClassInfos()); // AGDM addition
+ this->delete2DimArray(m_ppiBuildingFreeSpecialistCounts, GC.getNumBuildingClassInfos()); // AGDM addition
+ SAFE_DELETE_ARRAY(m_paiBuildingMilitaryProductionModifiers); // AGDM addition
+ SAFE_DELETE_ARRAY(m_paiBuildingFreeExperiences); // AGDM addition
+
SAFE_DELETE_ARRAY(m_pabHurry);
SAFE_DELETE_ARRAY(m_pabSpecialBuildingNotRequired);
SAFE_DELETE_ARRAY(m_pabSpecialistValid);
@@ -5656,6 +5676,14 @@ int CvCivicInfo::getBuildingHappinessChanges(int i) const
return m_paiBuildingHappinessChanges ? m_paiBuildingHappinessChanges[i] : -1;
}
+//Plako for RtR mod 22.7.2015
+int CvCivicInfo::getRtRExtraSpecialistCounts(int i) const
+{
+ FAssertMsg(i < GC.getNumSpecialistInfos(), "Index out of bounds");
+ FAssertMsg(i > -1, "Index out of bounds");
+ return m_paiRtRExtraSpecialistCounts ? m_paiRtRExtraSpecialistCounts[i] : -1;
+}
+
int CvCivicInfo::getBuildingHealthChanges(int i) const
{
FAssertMsg(i < GC.getNumBuildingClassInfos(), "Index out of bounds");
@@ -5691,6 +5719,104 @@ bool CvCivicInfo::isSpecialistValid(int i) const
return m_pabSpecialistValid ? m_pabSpecialistValid[i] : false;
}
+// AGDM addition:
+int CvCivicInfo::getBuildingYieldChanges(int i, int j) const
+{
+ FAssertMsg(i < GC.getNumBuildingClassInfos(), "Index out of bounds");
+ FAssertMsg(i > -1, "Index out of bounds");
+ FAssertMsg(j < NUM_YIELD_TYPES, "Index out of bounds");
+ FAssertMsg(j > -1, "Index out of bounds");
+ return m_ppiBuildingYieldChanges[i][j];
+}
+
+// AGDM addition:
+int *CvCivicInfo::getBuildingYieldChangeArray(int i) const
+{
+ FAssertMsg(i < GC.getNumBuildingClassInfos(), "Index out of bounds");
+ FAssertMsg(i > -1, "Index out of bounds");
+ return m_ppiBuildingYieldChanges[i];
+}
+
+// AGDM addition:
+int CvCivicInfo::getBuildingYieldModifiers(int i, int j) const
+{
+ FAssertMsg(i < GC.getNumBuildingClassInfos(), "Index out of bounds");
+ FAssertMsg(i > -1, "Index out of bounds");
+ FAssertMsg(j < NUM_YIELD_TYPES, "Index out of bounds");
+ FAssertMsg(j > -1, "Index out of bounds");
+ return m_ppiBuildingYieldModifiers[i][j];
+}
+
+// AGDM addition:
+int* CvCivicInfo::getBuildingYieldModifierArray(int i) const
+{
+ FAssertMsg(i < GC.getNumBuildingClassInfos(), "Index out of bounds");
+ FAssertMsg(i > -1, "Index out of bounds");
+ return m_ppiBuildingYieldModifiers[i];
+}
+
+// AGDM addition:
+int CvCivicInfo::getBuildingCommerceChanges(int i, int j) const
+{
+ FAssertMsg(i < GC.getNumBuildingClassInfos(), "Index out of bounds");
+ FAssertMsg(i > -1, "Index out of bounds");
+ FAssertMsg(j < NUM_COMMERCE_TYPES, "Index out of bounds");
+ FAssertMsg(j > -1, "Index out of bounds");
+ return m_ppiBuildingCommerceChanges[i][j];
+}
+
+// AGDM addition:
+int *CvCivicInfo::getBuildingCommerceChangeArray(int i) const
+{
+ FAssertMsg(i < GC.getNumBuildingClassInfos(), "Index out of bounds");
+ FAssertMsg(i > -1, "Index out of bounds");
+ return m_ppiBuildingCommerceChanges[i];
+}
+
+// AGDM addition:
+int CvCivicInfo::getBuildingCommerceModifiers(int i, int j) const
+{
+ FAssertMsg(i < GC.getNumBuildingClassInfos(), "Index out of bounds");
+ FAssertMsg(i > -1, "Index out of bounds");
+ FAssertMsg(j < NUM_COMMERCE_TYPES, "Index out of bounds");
+ FAssertMsg(j > -1, "Index out of bounds");
+ return m_ppiBuildingCommerceModifiers[i][j];
+}
+
+// AGDM addition:
+int *CvCivicInfo::getBuildingCommerceModifierArray(int i) const
+{
+ FAssertMsg(i < GC.getNumBuildingClassInfos(), "Index out of bounds");
+ FAssertMsg(i > -1, "Index out of bounds");
+ return m_ppiBuildingCommerceModifiers[i];
+}
+
+// AGDM addition:
+int CvCivicInfo::getBuildingFreeSpecialistCounts(int i, int j) const
+{
+ FAssertMsg(i < GC.getNumBuildingClassInfos(), "Index out of bounds");
+ FAssertMsg(i > -1, "Index out of bounds");
+ FAssertMsg(j < GC.getNumSpecialistInfos(), "Index out of bounds");
+ FAssertMsg(j > -1, "Index out of bounds");
+ return m_ppiBuildingFreeSpecialistCounts[i][j];
+}
+
+// AGDM addition:
+int CvCivicInfo::getBuildingFreeExperiences(int i) const
+{
+ FAssertMsg(i < GC.getNumBuildingClassInfos(), "Index out of bounds");
+ FAssertMsg(i > -1, "Index out of bounds");
+ return m_paiBuildingFreeExperiences ? m_paiBuildingFreeExperiences[i] : 0; //-1;
+}
+
+// AGDM addition:
+int CvCivicInfo::getBuildingMilitaryProductionModifiers(int i) const
+{
+ FAssertMsg(i < GC.getNumBuildingClassInfos(), "Index out of bounds");
+ FAssertMsg(i > -1, "Index out of bounds");
+ return m_paiBuildingMilitaryProductionModifiers ? m_paiBuildingMilitaryProductionModifiers[i] : 0; //-1;
+}
+
int CvCivicInfo::getImprovementYieldChanges(int i, int j) const
{
FAssertMsg(i < GC.getNumImprovementInfos(), "Index out of bounds");
@@ -5783,6 +5909,11 @@ void CvCivicInfo::read(FDataStreamBase* stream)
m_paiBuildingHappinessChanges = new int[GC.getNumBuildingClassInfos()];
stream->Read(GC.getNumBuildingClassInfos(), m_paiBuildingHappinessChanges);
+ //Plako for RtR mod 22.7.2015
+ SAFE_DELETE_ARRAY(m_paiRtRExtraSpecialistCounts);
+ m_paiRtRExtraSpecialistCounts = new int[GC.getNumSpecialistInfos()];
+ stream->Read(GC.getNumSpecialistInfos(), m_paiRtRExtraSpecialistCounts);
+
SAFE_DELETE_ARRAY(m_paiBuildingHealthChanges);
m_paiBuildingHealthChanges = new int[GC.getNumBuildingClassInfos()];
stream->Read(GC.getNumBuildingClassInfos(), m_paiBuildingHealthChanges);
@@ -5791,6 +5922,30 @@ void CvCivicInfo::read(FDataStreamBase* stream)
m_paiFeatureHappinessChanges = new int[GC.getNumFeatureInfos()];
stream->Read(GC.getNumFeatureInfos(), m_paiFeatureHappinessChanges);
+ // AGDM addition
+ this->delete2DimArray(m_ppiBuildingYieldChanges, GC.getNumBuildingClassInfos());
+ m_ppiBuildingYieldChanges = this->read2DimArray(stream, GC.getNumBuildingClassInfos(), NUM_YIELD_TYPES);
+ // AGDM addition
+ this->delete2DimArray(m_ppiBuildingYieldModifiers, GC.getNumBuildingClassInfos());
+ m_ppiBuildingYieldModifiers = this->read2DimArray(stream, GC.getNumBuildingClassInfos(), NUM_YIELD_TYPES);
+ // AGDM addition
+ this->delete2DimArray(m_ppiBuildingCommerceChanges, GC.getNumBuildingClassInfos());
+ m_ppiBuildingCommerceChanges = this->read2DimArray(stream, GC.getNumBuildingClassInfos(), NUM_COMMERCE_TYPES);
+ // AGDM addition
+ this->delete2DimArray(m_ppiBuildingCommerceModifiers, GC.getNumBuildingClassInfos());
+ m_ppiBuildingCommerceModifiers = this->read2DimArray(stream, GC.getNumBuildingClassInfos(), NUM_COMMERCE_TYPES);
+ // AGDM addition
+ this->delete2DimArray(m_ppiBuildingFreeSpecialistCounts, GC.getNumBuildingClassInfos());
+ m_ppiBuildingFreeSpecialistCounts = this->read2DimArray(stream, GC.getNumBuildingClassInfos(), GC.getNumSpecialistInfos());
+ // AGDM addition
+ SAFE_DELETE_ARRAY(m_paiBuildingMilitaryProductionModifiers);
+ m_paiBuildingMilitaryProductionModifiers = new int[GC.getNumBuildingClassInfos()];
+ stream->Read(GC.getNumBuildingClassInfos(), m_paiBuildingMilitaryProductionModifiers);
+ // AGDM addition
+ SAFE_DELETE_ARRAY(m_paiBuildingFreeExperiences);
+ m_paiBuildingFreeExperiences = new int[GC.getNumBuildingClassInfos()];
+ stream->Read(GC.getNumBuildingClassInfos(), m_paiBuildingFreeExperiences);
+
SAFE_DELETE_ARRAY(m_pabHurry);
m_pabHurry = new bool[GC.getNumHurryInfos()];
stream->Read(GC.getNumHurryInfos(), m_pabHurry);
@@ -5822,6 +5977,31 @@ void CvCivicInfo::read(FDataStreamBase* stream)
stream->ReadString(m_szWeLoveTheKingKey);
}
+void CvCivicInfo::delete2DimArray(int **arr, int size1)
+{
+ int i;
+ if (arr != NULL)
+ {
+ for(i=0;iRead(size2, arr[i]);
+ }
+ return arr;
+}
+
void CvCivicInfo::write(FDataStreamBase* stream)
{
CvInfoBase::write(stream);
@@ -5884,8 +6064,25 @@ void CvCivicInfo::write(FDataStreamBase* stream)
stream->Write(NUM_COMMERCE_TYPES, m_piCapitalCommerceModifier);
stream->Write(NUM_COMMERCE_TYPES, m_piSpecialistExtraCommerce);
stream->Write(GC.getNumBuildingClassInfos(), m_paiBuildingHappinessChanges);
+ stream->Write(GC.getNumSpecialistInfos(), m_paiRtRExtraSpecialistCounts); //Plako for RtR mod 22.7.2015
stream->Write(GC.getNumBuildingClassInfos(), m_paiBuildingHealthChanges);
stream->Write(GC.getNumFeatureInfos(), m_paiFeatureHappinessChanges);
+
+ // AGDM addition
+ this->write2DimArray(stream, m_ppiBuildingYieldChanges, GC.getNumBuildingClassInfos(), NUM_YIELD_TYPES);
+ // AGDM addition
+ this->write2DimArray(stream, m_ppiBuildingYieldModifiers, GC.getNumBuildingClassInfos(), NUM_YIELD_TYPES);
+ // AGDM addition
+ this->write2DimArray(stream, m_ppiBuildingCommerceChanges, GC.getNumBuildingClassInfos(), NUM_COMMERCE_TYPES);
+ // AGDM addition
+ this->write2DimArray(stream, m_ppiBuildingCommerceModifiers, GC.getNumBuildingClassInfos(), NUM_COMMERCE_TYPES);
+ // AGDM addition
+ this->write2DimArray(stream, m_ppiBuildingFreeSpecialistCounts, GC.getNumBuildingClassInfos(), GC.getNumSpecialistInfos());
+ // AGDM addition
+ stream->Write(GC.getNumBuildingClassInfos(), m_paiBuildingMilitaryProductionModifiers);
+ // AGDM addition
+ stream->Write(GC.getNumBuildingClassInfos(), m_paiBuildingFreeExperiences);
+
stream->Write(GC.getNumHurryInfos(), m_pabHurry);
stream->Write(GC.getNumSpecialBuildingInfos(), m_pabSpecialBuildingNotRequired);
stream->Write(GC.getNumSpecialistInfos(), m_pabSpecialistValid);
@@ -5899,6 +6096,15 @@ void CvCivicInfo::write(FDataStreamBase* stream)
stream->WriteString(m_szWeLoveTheKingKey);
}
+void CvCivicInfo::write2DimArray(FDataStreamBase* stream, int** arr, int size1, int size2)
+{
+ int i;
+ for(i=0;iWrite(size2, arr[i]);
+ }
+}
+
bool CvCivicInfo::read(CvXMLLoadUtility* pXML)
{
CvString szTextVal;
@@ -6028,9 +6234,235 @@ bool CvCivicInfo::read(CvXMLLoadUtility* pXML)
pXML->SetVariableListTagPair(&m_pabSpecialistValid, "SpecialistValids", sizeof(GC.getSpecialistInfo((SpecialistTypes)0)), GC.getNumSpecialistInfos());
pXML->SetVariableListTagPair(&m_paiBuildingHappinessChanges, "BuildingHappinessChanges", sizeof(GC.getBuildingClassInfo((BuildingClassTypes)0)), GC.getNumBuildingClassInfos());
+ pXML->SetVariableListTagPair(&m_paiRtRExtraSpecialistCounts, "RtRExtraSpecialistCounts", sizeof(GC.getSpecialistInfo((SpecialistTypes)0)), GC.getNumSpecialistInfos()); //Plako for RtR mod 22.7.2015
pXML->SetVariableListTagPair(&m_paiBuildingHealthChanges, "BuildingHealthChanges", sizeof(GC.getBuildingClassInfo((BuildingClassTypes)0)), GC.getNumBuildingClassInfos());
pXML->SetVariableListTagPair(&m_paiFeatureHappinessChanges, "FeatureHappinessChanges", sizeof(GC.getFeatureInfo((FeatureTypes)0)), GC.getNumFeatureInfos());
+ // AGDM addition:
+ pXML->Init2DIntList(&m_ppiBuildingYieldChanges, GC.getNumBuildingClassInfos(), NUM_YIELD_TYPES);
+ if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"BuildingSEYieldChanges"))
+ {
+ if (pXML->SkipToNextVal())
+ {
+ iNumSibs = gDLL->getXMLIFace()->GetNumChildren(pXML->GetXML());
+ if (gDLL->getXMLIFace()->SetToChild(pXML->GetXML()))
+ {
+ if (0 < iNumSibs)
+ {
+ for (j=0;jGetChildXmlValByName(szTextVal, "BuildingType");
+ iIndex = pXML->FindInInfoClass(szTextVal);
+
+ if (iIndex > -1)
+ {
+ // delete the array since it will be reallocated
+ SAFE_DELETE_ARRAY(m_ppiBuildingYieldChanges[iIndex]);
+ // if we can, set the current xml node to its next sibling
+ if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"BuildingYieldChanges"))
+ {
+ pXML->SetYields(&m_ppiBuildingYieldChanges[iIndex]);
+ gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
+ }
+ else
+ {
+ pXML->InitList(&m_ppiBuildingYieldChanges[iIndex], NUM_YIELD_TYPES);
+ }
+ }
+
+ if (!gDLL->getXMLIFace()->NextSibling(pXML->GetXML()))
+ {
+ break;
+ }
+ }
+ }
+
+ gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
+ }
+ }
+
+ gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
+ }
+
+ // AGDM addition:
+ pXML->Init2DIntList(&m_ppiBuildingYieldModifiers, GC.getNumBuildingClassInfos(), NUM_YIELD_TYPES);
+ if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"BuildingSEYieldModifiers"))
+ {
+ if (pXML->SkipToNextVal())
+ {
+ iNumSibs = gDLL->getXMLIFace()->GetNumChildren(pXML->GetXML());
+ if (gDLL->getXMLIFace()->SetToChild(pXML->GetXML()))
+ {
+ if (0 < iNumSibs)
+ {
+ for (j=0;jGetChildXmlValByName(szTextVal, "BuildingType");
+ iIndex = pXML->FindInInfoClass(szTextVal);
+
+ if (iIndex > -1)
+ {
+ // delete the array since it will be reallocated
+ SAFE_DELETE_ARRAY(m_ppiBuildingYieldModifiers[iIndex]);
+ // if we can, set the current xml node to its next sibling
+ if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"BuildingYieldModifiers"))
+ {
+ pXML->SetYields(&m_ppiBuildingYieldModifiers[iIndex]);
+ gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
+ }
+ else
+ {
+ pXML->InitList(&m_ppiBuildingYieldModifiers[iIndex], NUM_YIELD_TYPES);
+ }
+ }
+
+ if (!gDLL->getXMLIFace()->NextSibling(pXML->GetXML()))
+ {
+ break;
+ }
+ }
+ }
+
+ gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
+ }
+ }
+
+ gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
+ }
+
+ // AGDM addition:
+ pXML->Init2DIntList(&m_ppiBuildingCommerceChanges, GC.getNumBuildingClassInfos(), NUM_COMMERCE_TYPES);
+ if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"BuildingSECommerceChanges"))
+ {
+ if (pXML->SkipToNextVal())
+ {
+ iNumSibs = gDLL->getXMLIFace()->GetNumChildren(pXML->GetXML());
+ if (gDLL->getXMLIFace()->SetToChild(pXML->GetXML()))
+ {
+ if (0 < iNumSibs)
+ {
+ for (j=0;jGetChildXmlValByName(szTextVal, "BuildingType");
+ iIndex = pXML->FindInInfoClass(szTextVal);
+
+ if (iIndex > -1)
+ {
+ // delete the array since it will be reallocated
+ SAFE_DELETE_ARRAY(m_ppiBuildingCommerceChanges[iIndex]);
+ // if we can, set the current xml node to its next sibling
+ if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"BuildingCommerceChanges"))
+ {
+ pXML->SetCommerce(&m_ppiBuildingCommerceChanges[iIndex]);
+ gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
+ }
+ else
+ {
+ pXML->InitList(&m_ppiBuildingCommerceChanges[iIndex], NUM_COMMERCE_TYPES);
+ }
+ }
+
+ if (!gDLL->getXMLIFace()->NextSibling(pXML->GetXML()))
+ {
+ break;
+ }
+ }
+ }
+
+ gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
+ }
+ }
+
+ gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
+ }
+
+ // AGDM addition:
+ pXML->Init2DIntList(&m_ppiBuildingCommerceModifiers, GC.getNumBuildingClassInfos(), NUM_COMMERCE_TYPES);
+ if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"BuildingSECommerceModifiers"))
+ {
+ if (pXML->SkipToNextVal())
+ {
+ iNumSibs = gDLL->getXMLIFace()->GetNumChildren(pXML->GetXML());
+ if (gDLL->getXMLIFace()->SetToChild(pXML->GetXML()))
+ {
+ if (0 < iNumSibs)
+ {
+ for (j=0;jGetChildXmlValByName(szTextVal, "BuildingType");
+ iIndex = pXML->FindInInfoClass(szTextVal);
+
+ if (iIndex > -1)
+ {
+ // delete the array since it will be reallocated
+ SAFE_DELETE_ARRAY(m_ppiBuildingCommerceModifiers[iIndex]);
+ // if we can, set the current xml node to its next sibling
+ if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"BuildingCommerceModifiers"))
+ {
+ pXML->SetCommerce(&m_ppiBuildingCommerceModifiers[iIndex]);
+ gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
+ }
+ else
+ {
+ pXML->InitList(&m_ppiBuildingCommerceModifiers[iIndex], NUM_COMMERCE_TYPES);
+ }
+ }
+
+ if (!gDLL->getXMLIFace()->NextSibling(pXML->GetXML()))
+ {
+ break;
+ }
+ }
+ }
+
+ gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
+ }
+ }
+
+ gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
+ }
+
+ // AGDM addition:
+ pXML->Init2DIntList(&m_ppiBuildingFreeSpecialistCounts, GC.getNumBuildingClassInfos(), GC.getNumSpecialistInfos());
+ if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"BuildingSEFreeSpecialistCounts"))
+ {
+ if (pXML->SkipToNextVal())
+ {
+ iNumSibs = gDLL->getXMLIFace()->GetNumChildren(pXML->GetXML());
+ if (gDLL->getXMLIFace()->SetToChild(pXML->GetXML()))
+ {
+ if (0 < iNumSibs)
+ {
+ for (j=0;jGetChildXmlValByName(szTextVal, "BuildingType");
+ iIndex = pXML->FindInInfoClass(szTextVal);
+
+ if (iIndex > -1)
+ {
+ // delete the array since it will be reallocated
+ SAFE_DELETE_ARRAY(m_ppiBuildingFreeSpecialistCounts[iIndex]);
+ pXML->SetVariableListTagPair(&m_ppiBuildingFreeSpecialistCounts[iIndex], "BuildingFreeSpecialistCounts", sizeof(GC.getSpecialistInfo((SpecialistTypes)0)), GC.getNumSpecialistInfos());
+ }
+
+ if (!gDLL->getXMLIFace()->NextSibling(pXML->GetXML()))
+ {
+ break;
+ }
+ }
+ }
+
+ gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
+ }
+ }
+
+ gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
+ }
+ // AGDM addition:
+ pXML->SetVariableListTagPair(&m_paiBuildingFreeExperiences, "BuildingSEFreeExperiences", sizeof(GC.getBuildingClassInfo((BuildingClassTypes)0)), GC.getNumBuildingClassInfos());
+ // AGDM addition:
+ pXML->SetVariableListTagPair(&m_paiBuildingMilitaryProductionModifiers, "BuildingSEMilitaryProductionModifiers", sizeof(GC.getBuildingClassInfo((BuildingClassTypes)0)), GC.getNumBuildingClassInfos());
+
// initialize the boolean list to the correct size and all the booleans to false
FAssertMsg((GC.getNumImprovementInfos() > 0) && (NUM_YIELD_TYPES) > 0,"either the number of improvement infos is zero or less or the number of yield types is zero or less");
pXML->Init2DIntList(&m_ppiImprovementYieldChanges, GC.getNumImprovementInfos(), NUM_YIELD_TYPES);
@@ -9082,6 +9514,7 @@ m_iActionSoundScriptId(0),
m_iDerivativeCiv(NO_CIVILIZATION),
m_bPlayable(false),
m_bAIPlayable(false),
+m_pbTraits(NULL), // AGDM addition
m_piCivilizationBuildings(NULL),
m_piCivilizationUnits(NULL),
m_piCivilizationFreeUnitsClass(NULL),
@@ -9103,6 +9536,7 @@ m_paszCityNames(NULL)
//------------------------------------------------------------------------------------------------------
CvCivilizationInfo::~CvCivilizationInfo()
{
+ SAFE_DELETE_ARRAY(m_pbTraits); // AGDM addition
SAFE_DELETE_ARRAY(m_piCivilizationBuildings);
SAFE_DELETE_ARRAY(m_piCivilizationUnits);
SAFE_DELETE_ARRAY(m_piCivilizationFreeUnitsClass);
@@ -9214,6 +9648,14 @@ void CvCivilizationInfo::setArtDefineTag(const TCHAR* szVal)
// Arrays
+// AGDM addition
+bool CvCivilizationInfo::hasTrait(int i) const
+{
+ FAssertMsg(i < GC.getNumTraitInfos(), "Index out of bounds");
+ FAssertMsg(i > -1, "Index out of bounds");
+ return m_pbTraits ? m_pbTraits[i] : false;
+}
+
int CvCivilizationInfo::getCivilizationBuildings(int i) const
{
FAssertMsg(i < GC.getNumBuildingClassInfos(), "Index out of bounds");
@@ -9322,6 +9764,11 @@ void CvCivilizationInfo::read(FDataStreamBase* stream)
// Arrays
+ // AGDM addition
+ SAFE_DELETE_ARRAY(m_pbTraits);
+ m_pbTraits = new bool[GC.getNumTraitInfos()];
+ stream->Read(GC.getNumTraitInfos(), m_pbTraits);
+
SAFE_DELETE_ARRAY(m_piCivilizationBuildings);
m_piCivilizationBuildings = new int[GC.getNumBuildingClassInfos()];
stream->Read(GC.getNumBuildingClassInfos(), m_piCivilizationBuildings);
@@ -9384,6 +9831,7 @@ void CvCivilizationInfo::write(FDataStreamBase* stream)
// Arrays
+ stream->Write(GC.getNumTraitInfos(), m_pbTraits); // AGDM addition
stream->Write(GC.getNumBuildingClassInfos(), m_piCivilizationBuildings);
stream->Write(GC.getNumUnitClassInfos(), m_piCivilizationUnits);
stream->Write(GC.getNumUnitClassInfos(), m_piCivilizationFreeUnitsClass);
@@ -9407,6 +9855,9 @@ bool CvCivilizationInfo::read(CvXMLLoadUtility* pXML)
int j, iNumSibs;
+ // AGDM addition
+ pXML->SetVariableListTagPair(&m_pbTraits, "Traits", sizeof(GC.getTraitInfo((TraitTypes)0)), GC.getNumTraitInfos());
+
pXML->GetChildXmlValByName(m_szShortDescriptionKey, "ShortDescription");
// Get the Text from Text/Civ4GameTextXML.xml
@@ -13070,9 +13521,11 @@ m_iHillsChange(0),
m_iPeakChange(0),
m_iLakeChange(0),
m_iCityChange(0),
+m_iCapitalChange(0), // AGDM addition
m_iPopulationChangeOffset(0),
m_iPopulationChangeDivisor(0),
m_iMinCity(0),
+m_iMinCapital(0), // AGDM addition
m_iTradeModifier(0),
m_iGoldenAgeYield(0),
m_iGoldenAgeYieldThreshold(0),
@@ -13125,6 +13578,11 @@ int CvYieldInfo::getCityChange() const
return m_iCityChange;
}
+int CvYieldInfo::getCapitalChange() const // AGDM addition
+{
+ return m_iCapitalChange;
+}
+
int CvYieldInfo::getPopulationChangeOffset() const
{
return m_iPopulationChangeOffset;
@@ -13140,6 +13598,11 @@ int CvYieldInfo::getMinCity() const
return m_iMinCity;
}
+int CvYieldInfo::getMinCapital() const // AGDM addition
+{
+ return m_iMinCapital;
+}
+
int CvYieldInfo::getTradeModifier() const
{
return m_iTradeModifier;
@@ -13188,9 +13651,11 @@ bool CvYieldInfo::read(CvXMLLoadUtility* pXML)
pXML->GetChildXmlValByName(&m_iPeakChange, "iPeakChange");
pXML->GetChildXmlValByName(&m_iLakeChange, "iLakeChange");
pXML->GetChildXmlValByName(&m_iCityChange, "iCityChange");
+ pXML->GetChildXmlValByName(&m_iCapitalChange, "iCapitalChange"); // AGDM addition
pXML->GetChildXmlValByName(&m_iPopulationChangeOffset, "iPopulationChangeOffset");
pXML->GetChildXmlValByName(&m_iPopulationChangeDivisor, "iPopulationChangeDivisor");
pXML->GetChildXmlValByName(&m_iMinCity, "iMinCity");
+ pXML->GetChildXmlValByName(&m_iMinCapital, "iMinCapital"); // AGDM addition
pXML->GetChildXmlValByName(&m_iTradeModifier, "iTradeModifier");
pXML->GetChildXmlValByName(&m_iGoldenAgeYield, "iGoldenAgeYield");
pXML->GetChildXmlValByName(&m_iGoldenAgeYieldThreshold, "iGoldenAgeYieldThreshold");
diff --git a/CvGameCoreDLL/CvInfos.h b/CvGameCoreDLL/CvInfos.h
index 735fe66..2e5cfd9 100644
--- a/CvGameCoreDLL/CvInfos.h
+++ b/CvGameCoreDLL/CvInfos.h
@@ -1363,6 +1363,7 @@ class CvCivicInfo :
int getSpecialistExtraCommerce(int i) const; // Exposed to Python
int* getSpecialistExtraCommerceArray() const;
int getBuildingHappinessChanges(int i) const; // Exposed to Python
+ int getRtRExtraSpecialistCounts(int i) const; //Plako for RtR mod 21.7.2015
int getBuildingHealthChanges(int i) const; // Exposed to Python
int getFeatureHappinessChanges(int i) const; // Exposed to Python
@@ -1372,8 +1373,23 @@ class CvCivicInfo :
int getImprovementYieldChanges(int i, int j) const; // Exposed to Python
+ int getBuildingYieldChanges(int i, int j) const; // AGDM addition
+ int *getBuildingYieldChangeArray(int i) const; // AGDM addition
+ int getBuildingYieldModifiers(int i, int j) const; // AGDM addition
+ int *getBuildingYieldModifierArray(int i) const; // AGDM addition
+ int getBuildingCommerceChanges(int i, int j) const; // AGDM addition
+ int *getBuildingCommerceChangeArray(int i) const; // AGDM addition
+ int getBuildingCommerceModifiers(int i, int j) const; // AGDM addition
+ int *getBuildingCommerceModifierArray(int i) const; // AGDM addition
+ int getBuildingFreeSpecialistCounts(int i, int j) const; // AGDM addition
+ int getBuildingFreeExperiences(int i) const; // AGDM addition
+ int getBuildingMilitaryProductionModifiers(int i) const; // AGDM addition
+
+ void delete2DimArray(int **arr, int size1);
+ int **read2DimArray(FDataStreamBase* stream, int size1, int size2);
void read(FDataStreamBase* stream);
void write(FDataStreamBase* stream);
+ void write2DimArray(FDataStreamBase* stream, int** arr, int size1, int size2);
bool read(CvXMLLoadUtility* pXML);
@@ -1437,9 +1453,18 @@ class CvCivicInfo :
int* m_piCapitalCommerceModifier;
int* m_piSpecialistExtraCommerce;
int* m_paiBuildingHappinessChanges;
+ int* m_paiRtRExtraSpecialistCounts; //Plako for RtR mod 22.7.2015
int* m_paiBuildingHealthChanges;
int* m_paiFeatureHappinessChanges;
+ int** m_ppiBuildingYieldChanges; // AGDM addition, xml tag
+ int** m_ppiBuildingYieldModifiers; // AGDM addition, xml tag
+ int** m_ppiBuildingCommerceChanges; // AGDM addition, xml tag
+ int** m_ppiBuildingCommerceModifiers; // AGDM addition, xml tag
+ int** m_ppiBuildingFreeSpecialistCounts; // AGDM addition, xml tag
+ int* m_paiBuildingMilitaryProductionModifiers; // AGDM addition, xml tag
+ int* m_paiBuildingFreeExperiences; // AGDM addition, xml tag
+
bool* m_pabHurry;
bool* m_pabSpecialBuildingNotRequired;
bool* m_pabSpecialistValid;
@@ -2154,6 +2179,7 @@ class CvCivilizationInfo :
DllExport void setArtDefineTag(const TCHAR* szVal);
// Arrays
+ bool hasTrait(int i) const; // AGDM addition
DllExport int getCivilizationBuildings(int i) const; // Exposed to Python
DllExport int getCivilizationUnits(int i) const; // Exposed to Python
DllExport int getCivilizationFreeUnitsClass(int i) const; // Exposed to Python
@@ -2198,6 +2224,8 @@ class CvCivilizationInfo :
CvWString m_szAdjectiveKey;
// Arrays
+ bool* m_pbTraits; // AGDM addition
+
int* m_piCivilizationBuildings;
int* m_piCivilizationUnits;
int* m_piCivilizationFreeUnitsClass;
@@ -3261,9 +3289,11 @@ class CvYieldInfo :
int getPeakChange() const; // Exposed to Python
int getLakeChange() const; // Exposed to Python
int getCityChange() const; // Exposed to Python
+ int getCapitalChange() const; // Exposed to Python, AGDM addition
int getPopulationChangeOffset() const; // Exposed to Python
int getPopulationChangeDivisor() const; // Exposed to Python
int getMinCity() const; // Exposed to Python
+ int getMinCapital() const; // Exposed to Python. AGDM addition
int getTradeModifier() const; // Exposed to Python
int getGoldenAgeYield() const; // Exposed to Python
int getGoldenAgeYieldThreshold() const; // Exposed to Python
@@ -3284,9 +3314,11 @@ class CvYieldInfo :
int m_iPeakChange;
int m_iLakeChange;
int m_iCityChange;
+ int m_iCapitalChange; // AGDM addition
int m_iPopulationChangeOffset;
int m_iPopulationChangeDivisor;
int m_iMinCity;
+ int m_iMinCapital; // AGDM addition
int m_iTradeModifier;
int m_iGoldenAgeYield;
int m_iGoldenAgeYieldThreshold;
diff --git a/CvGameCoreDLL/CvPlayer.cpp b/CvGameCoreDLL/CvPlayer.cpp
index a90503a..51b874b 100644
--- a/CvGameCoreDLL/CvPlayer.cpp
+++ b/CvGameCoreDLL/CvPlayer.cpp
@@ -2228,7 +2228,8 @@ bool CvPlayer::hasTrait(TraitTypes eTrait) const
{
FAssertMsg((getLeaderType() >= 0), "getLeaderType() is less than zero");
FAssertMsg((eTrait >= 0), "eTrait is less than zero");
- return GC.getLeaderHeadInfo(getLeaderType()).hasTrait(eTrait);
+ return GC.getLeaderHeadInfo(getLeaderType()).hasTrait(eTrait)
+ || GC.getCivilizationInfo(getCivilizationType()).hasTrait(eTrait); // AGDM addition
}
bool CvPlayer::isHuman() const
@@ -3889,6 +3890,14 @@ bool CvPlayer::canTradeItem(PlayerTypes eWhoTo, TradeData item, bool bTestDenial
break;
case TRADE_MAPS:
+
+ //Plako for RtR mod No barbs = no map trading
+ if (GC.getGameINLINE().isOption(GAMEOPTION_NO_BARBARIANS))
+ {
+ return false;
+ }
+ //end RtR mod
+
if (getTeam() != GET_PLAYER(eWhoTo).getTeam())
{
if (GET_TEAM(getTeam()).isMapTrading() || GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isMapTrading())
@@ -6411,6 +6420,16 @@ int CvPlayer::calculateResearchModifier(TechTypes eTech) const
}
}
+ //novice: Hard lower cap used to decrease known tech boni for games with few players
+ int iPossibleKnownCountHardCapLower = GC.getDefineINT("TECH_COST_CIV_COUNT_HARD_CAP_LOWER");
+ if(iPossibleKnownCountHardCapLower > 0) {
+ // There's a hard cap; cap the number of civs at the hard cap.
+ // This decreases known tech boni for games with fewer players than the hard cap.
+ if(iPossibleKnownCount < iPossibleKnownCountHardCapLower) {
+ iPossibleKnownCount = iPossibleKnownCountHardCapLower;
+ }
+ }
+
if (iPossibleKnownCount > 0)
{
float fMultiplierPerEra = GC.getDefineFLOAT("TECH_COST_MODIFIER_PER_ERA_MULTIPLIER");
@@ -9176,6 +9195,9 @@ void CvPlayer::setCapitalCity(CvCity* pNewCapitalCity)
pOldCapitalCity = getCapitalCity();
+ if (pOldCapitalCity != NULL) pOldCapitalCity->plot()->updateYield(); // AGDM addition
+ if (pNewCapitalCity != NULL) pNewCapitalCity->plot()->updateYield(); // AGDM addition
+
if (pOldCapitalCity != pNewCapitalCity)
{
bUpdatePlotGroups = ((pOldCapitalCity == NULL) || (pNewCapitalCity == NULL) || (pOldCapitalCity->plot()->getOwnerPlotGroup() != pNewCapitalCity->plot()->getOwnerPlotGroup()));
@@ -9920,29 +9942,14 @@ void CvPlayer::setEndTurn(bool bNewValue)
setAutoMoves(true);
//Plako for RBmod (monitor)
- if(gDLL->IsPitbossHost() && GC.getDefineINT("ENABLE_PITBOSS_PORTAL_LOGGING") > 0) {
- if (bNewValue) {
- time_t rawtime;
- struct tm * timeinfo;
- time ( &rawtime );
- timeinfo = localtime ( &rawtime );
- CvString timeString = asctime (timeinfo);
- CvString from = "\n";
- CvString to = " ";
- GC.getGameINLINE().replace(timeString, from, to);
-
- std::ostringstream convertId;
- convertId << getID();
-
- std::ostringstream convertGameTurn;
- convertGameTurn << GC.getGameINLINE().getGameTurn();
-
- CvString eventText = timeString + " --- " + (CvString)(getName()) + " --- END TURN --- ";
- eventText += convertId.str() + " --- ";
- eventText += convertGameTurn.str() + "\n";
- GC.getGameINLINE().appendBeginAndResize(GC.getGameINLINE().getLogfilePath("event"), eventText);
- GC.getGameINLINE().appendBeginAndResize(GC.getGameINLINE().getLogfilePath("gamestate_eot" + convertGameTurn.str() + "_player" + convertId.str()), "State of game: Player " + convertId.str() + " just ended turn " + convertGameTurn.str());
- }
+ GC.getGameINLINE().logEvent(getID(), "END TURN");
+ // Novice: Log game state when player ends turn
+ GC.getGameINLINE().logGameStateString(getID());
+ // Novice: Trigger autosave if in pitboss mode
+ if(gDLL->IsPitbossHost() && GC.getDefineINT("ENABLE_EXTENDED_RECOVERY_SAVES") > 0) {
+ CvString saveName = (CvString)(getName()) + "_end_turn_" + GC.getGameINLINE().getLocalTimeString(true) + ".CivBeyondSwordSave";
+ CvString fileName = GC.getGameINLINE().getLogfilePath(saveName, false);
+ gDLL->getEngineIFace()->SaveGame(fileName, SAVEGAME_RECOVERY);
}
}
}
@@ -12459,6 +12466,9 @@ void CvPlayer::clearDiplomacy()
const CvDiploQueue& CvPlayer::getDiplomacy() const
{
+ if (GC.getGameINLINE().isPaused() && GC.getGameINLINE().isPitboss() && GC.getDefineINT("ENABLE_PITBOSS_PAUSE_FIX") > 0) {
+ return m_listDiplomacyEmpty;
+ }
return (m_listDiplomacy);
}
@@ -15580,6 +15590,28 @@ void CvPlayer::processCivics(CivicTypes eCivic, int iChange)
changeExtraBuildingHappiness(eOurBuilding, (GC.getCivicInfo(eCivic).getBuildingHappinessChanges(iI) * iChange));
changeExtraBuildingHealth(eOurBuilding, (GC.getCivicInfo(eCivic).getBuildingHealthChanges(iI) * iChange));
}
+ // AGDM addition:
+ // TODO: Process this when a city is aquired as well. (I.e. a city changes ownership; thus the civics of the city changes
+ int iLoop;
+ for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
+ {
+ for (iJ = 0; iJ < NUM_YIELD_TYPES; ++iJ)
+ {
+ pLoopCity->changeBuildingYieldChange((BuildingClassTypes)iI, (YieldTypes)iJ, (GC.getCivicInfo(eCivic)).getBuildingYieldChanges(iI, iJ) * iChange);
+ pLoopCity->changeYieldRateModifier((YieldTypes)iJ, pLoopCity->getNumActiveBuilding(eOurBuilding) * GC.getCivicInfo(eCivic).getBuildingYieldModifiers(iI, iJ) * iChange);
+ }
+ for (iJ = 0; iJ < NUM_COMMERCE_TYPES; ++iJ)
+ {
+ pLoopCity->changeBuildingCommerceChange((BuildingClassTypes)iI, (CommerceTypes)iJ, (GC.getCivicInfo(eCivic)).getBuildingCommerceChanges(iI, iJ) * iChange);
+ pLoopCity->changeCommerceRateModifier((CommerceTypes)iJ, pLoopCity->getNumActiveBuilding(eOurBuilding) * GC.getCivicInfo(eCivic).getBuildingCommerceModifiers(iI, iJ) * iChange);
+ }
+ for (iJ = 0; iJ < GC.getNumSpecialistInfos(); iJ++)
+ {
+ pLoopCity->changeFreeSpecialistCount((SpecialistTypes)iJ, pLoopCity->getNumActiveBuilding(eOurBuilding) * GC.getCivicInfo(eCivic).getBuildingFreeSpecialistCounts(iI, iJ) * iChange);
+ }
+ pLoopCity->changeMilitaryProductionModifier(pLoopCity->getNumActiveBuilding(eOurBuilding) * GC.getCivicInfo(eCivic).getBuildingMilitaryProductionModifiers(iI) * iChange);
+ pLoopCity->changeFreeExperience(pLoopCity->getNumActiveBuilding(eOurBuilding) * GC.getCivicInfo(eCivic).getBuildingFreeExperiences(iI) * iChange);
+ }
}
for (iI = 0; iI < GC.getNumFeatureInfos(); iI++)
@@ -19675,7 +19707,11 @@ void CvPlayer::launch(VictoryTypes eVictory)
kTeam.finalizeProjectArtTypes();
kTeam.setVictoryCountdown(eVictory, kTeam.getVictoryDelay(eVictory));
- gDLL->getEngineIFace()->AddLaunch(getID());
+ //Plako for RtR mod - Prevent Space ship launch crash (pitboss)
+ //Based on K-Mod change (Creadits to karadoc)
+ if (!gDLL->IsPitbossHost())
+ gDLL->getEngineIFace()->AddLaunch(getID());
+ //RtR mod end
kTeam.setCanLaunch(eVictory, false);
diff --git a/CvGameCoreDLL/CvPlayer.h b/CvGameCoreDLL/CvPlayer.h
index 3fe1adb..888c940 100644
--- a/CvGameCoreDLL/CvPlayer.h
+++ b/CvGameCoreDLL/CvPlayer.h
@@ -1249,7 +1249,10 @@ class CvPlayer
CvMessageQueue m_listGameMessages;
CvPopupQueue m_listPopups;
- CvDiploQueue m_listDiplomacy;
+ CvDiploQueue m_listDiplomacy;
+
+ // novice for RtR
+ CvDiploQueue m_listDiplomacyEmpty;
CvTurnScoreMap m_mapScoreHistory;
CvTurnScoreMap m_mapEconomyHistory;
diff --git a/CvGameCoreDLL/CvPlayerAI.cpp b/CvGameCoreDLL/CvPlayerAI.cpp
new file mode 100644
index 0000000..750bc5f
--- /dev/null
+++ b/CvGameCoreDLL/CvPlayerAI.cpp
@@ -0,0 +1,16986 @@
+// playerAI.cpp
+
+#include "CvGameCoreDLL.h"
+#include "CvPlayerAI.h"
+#include "CvRandom.h"
+#include "CvGlobals.h"
+#include "CvGameCoreUtils.h"
+#include "CvMap.h"
+#include "CvArea.h"
+#include "CvPlot.h"
+#include "CvGameAI.h"
+#include "CvTeamAI.h"
+#include "CvGameCoreUtils.h"
+#include "CvDiploParameters.h"
+#include "CvInitCore.h"
+#include "CyArgsList.h"
+#include "CvDLLInterfaceIFaceBase.h"
+#include "CvDLLEntityIFaceBase.h"
+#include "CvDLLPythonIFaceBase.h"
+#include "CvDLLEngineIFaceBase.h"
+#include "CvInfos.h"
+#include "CvPopupInfo.h"
+#include "FProfiler.h"
+#include "CvDLLFAStarIFaceBase.h"
+#include "FAStarNode.h"
+#include "CvEventReporter.h"
+
+#define DANGER_RANGE (4)
+#define GREATER_FOUND_RANGE (5)
+#define CIVIC_CHANGE_DELAY (25)
+#define RELIGION_CHANGE_DELAY (15)
+
+// statics
+
+CvPlayerAI* CvPlayerAI::m_aPlayers = NULL;
+
+void CvPlayerAI::initStatics()
+{
+ m_aPlayers = new CvPlayerAI[MAX_PLAYERS];
+ for (int iI = 0; iI < MAX_PLAYERS; iI++)
+ {
+ m_aPlayers[iI].m_eID = ((PlayerTypes)iI);
+ }
+}
+
+void CvPlayerAI::freeStatics()
+{
+ SAFE_DELETE_ARRAY(m_aPlayers);
+}
+
+bool CvPlayerAI::areStaticsInitialized()
+{
+ if(m_aPlayers == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+DllExport CvPlayerAI& CvPlayerAI::getPlayerNonInl(PlayerTypes ePlayer)
+{
+ return getPlayer(ePlayer);
+}
+
+// Public Functions...
+
+CvPlayerAI::CvPlayerAI()
+{
+ m_aiNumTrainAIUnits = new int[NUM_UNITAI_TYPES];
+ m_aiNumAIUnits = new int[NUM_UNITAI_TYPES];
+ m_aiSameReligionCounter = new int[MAX_PLAYERS];
+ m_aiDifferentReligionCounter = new int[MAX_PLAYERS];
+ m_aiFavoriteCivicCounter = new int[MAX_PLAYERS];
+ m_aiBonusTradeCounter = new int[MAX_PLAYERS];
+ m_aiPeacetimeTradeValue = new int[MAX_PLAYERS];
+ m_aiPeacetimeGrantValue = new int[MAX_PLAYERS];
+ m_aiGoldTradedTo = new int[MAX_PLAYERS];
+ m_aiAttitudeExtra = new int[MAX_PLAYERS];
+
+ m_abFirstContact = new bool[MAX_PLAYERS];
+
+ m_aaiContactTimer = new int*[MAX_PLAYERS];
+ for (int i = 0; i < MAX_PLAYERS; i++)
+ {
+ m_aaiContactTimer[i] = new int[NUM_CONTACT_TYPES];
+ }
+
+ m_aaiMemoryCount = new int*[MAX_PLAYERS];
+ for (int i = 0; i < MAX_PLAYERS; i++)
+ {
+ m_aaiMemoryCount[i] = new int[NUM_MEMORY_TYPES];
+ }
+
+ m_aiAverageYieldMultiplier = new int[NUM_YIELD_TYPES];
+ m_aiAverageCommerceMultiplier = new int[NUM_COMMERCE_TYPES];
+ m_aiAverageCommerceExchange = new int[NUM_COMMERCE_TYPES];
+
+ m_aiBonusValue = NULL;
+ m_aiUnitClassWeights = NULL;
+ m_aiUnitCombatWeights = NULL;
+ m_aiCloseBordersAttitudeCache = new int[MAX_PLAYERS];
+
+ AI_reset(true);
+}
+
+
+CvPlayerAI::~CvPlayerAI()
+{
+ AI_uninit();
+
+ SAFE_DELETE_ARRAY(m_aiNumTrainAIUnits);
+ SAFE_DELETE_ARRAY(m_aiNumAIUnits);
+ SAFE_DELETE_ARRAY(m_aiSameReligionCounter);
+ SAFE_DELETE_ARRAY(m_aiDifferentReligionCounter);
+ SAFE_DELETE_ARRAY(m_aiFavoriteCivicCounter);
+ SAFE_DELETE_ARRAY(m_aiBonusTradeCounter);
+ SAFE_DELETE_ARRAY(m_aiPeacetimeTradeValue);
+ SAFE_DELETE_ARRAY(m_aiPeacetimeGrantValue);
+ SAFE_DELETE_ARRAY(m_aiGoldTradedTo);
+ SAFE_DELETE_ARRAY(m_aiAttitudeExtra);
+ SAFE_DELETE_ARRAY(m_abFirstContact);
+ for (int i = 0; i < MAX_PLAYERS; i++)
+ {
+ SAFE_DELETE_ARRAY(m_aaiContactTimer[i]);
+ }
+ SAFE_DELETE_ARRAY(m_aaiContactTimer);
+
+ for (int i = 0; i < MAX_PLAYERS; i++)
+ {
+ SAFE_DELETE_ARRAY(m_aaiMemoryCount[i]);
+ }
+ SAFE_DELETE_ARRAY(m_aaiMemoryCount);
+
+ SAFE_DELETE_ARRAY(m_aiAverageYieldMultiplier);
+ SAFE_DELETE_ARRAY(m_aiAverageCommerceMultiplier);
+ SAFE_DELETE_ARRAY(m_aiAverageCommerceExchange);
+ SAFE_DELETE_ARRAY(m_aiCloseBordersAttitudeCache);
+}
+
+
+void CvPlayerAI::AI_init()
+{
+ AI_reset(false);
+
+ //--------------------------------
+ // Init other game data
+ if ((GC.getInitCore().getSlotStatus(getID()) == SS_TAKEN) || (GC.getInitCore().getSlotStatus(getID()) == SS_COMPUTER))
+ {
+ FAssert(getPersonalityType() != NO_LEADER);
+ AI_setPeaceWeight(GC.getLeaderHeadInfo(getPersonalityType()).getBasePeaceWeight() + GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getPeaceWeightRand(), "AI Peace Weight"));
+ AI_setEspionageWeight(GC.getLeaderHeadInfo(getPersonalityType()).getEspionageWeight());
+ //AI_setCivicTimer(((getMaxAnarchyTurns() == 0) ? (GC.getDefineINT("MIN_REVOLUTION_TURNS") * 2) : CIVIC_CHANGE_DELAY) / 2);
+ AI_setReligionTimer(1);
+ AI_setCivicTimer((getMaxAnarchyTurns() == 0) ? 1 : 2);
+ }
+}
+
+
+void CvPlayerAI::AI_uninit()
+{
+ SAFE_DELETE_ARRAY(m_aiBonusValue);
+ SAFE_DELETE_ARRAY(m_aiUnitClassWeights);
+ SAFE_DELETE_ARRAY(m_aiUnitCombatWeights);
+}
+
+
+void CvPlayerAI::AI_reset(bool bConstructor)
+{
+ int iI;
+
+ AI_uninit();
+
+ m_iPeaceWeight = 0;
+ m_iEspionageWeight = 0;
+ m_iAttackOddsChange = 0;
+ m_iCivicTimer = 0;
+ m_iReligionTimer = 0;
+ m_iExtraGoldTarget = 0;
+
+ for (iI = 0; iI < NUM_UNITAI_TYPES; iI++)
+ {
+ m_aiNumTrainAIUnits[iI] = 0;
+ m_aiNumAIUnits[iI] = 0;
+ }
+
+ for (iI = 0; iI < MAX_PLAYERS; iI++)
+ {
+ m_aiSameReligionCounter[iI] = 0;
+ m_aiDifferentReligionCounter[iI] = 0;
+ m_aiFavoriteCivicCounter[iI] = 0;
+ m_aiBonusTradeCounter[iI] = 0;
+ m_aiPeacetimeTradeValue[iI] = 0;
+ m_aiPeacetimeGrantValue[iI] = 0;
+ m_aiGoldTradedTo[iI] = 0;
+ m_aiAttitudeExtra[iI] = 0;
+ m_abFirstContact[iI] = false;
+ for (int iJ = 0; iJ < NUM_CONTACT_TYPES; iJ++)
+ {
+ m_aaiContactTimer[iI][iJ] = 0;
+ }
+ for (int iJ = 0; iJ < NUM_MEMORY_TYPES; iJ++)
+ {
+ m_aaiMemoryCount[iI][iJ] = 0;
+ }
+
+ if (!bConstructor && getID() != NO_PLAYER)
+ {
+ PlayerTypes eLoopPlayer = (PlayerTypes) iI;
+ CvPlayerAI& kLoopPlayer = GET_PLAYER(eLoopPlayer);
+ kLoopPlayer.m_aiSameReligionCounter[getID()] = 0;
+ kLoopPlayer.m_aiDifferentReligionCounter[getID()] = 0;
+ kLoopPlayer.m_aiFavoriteCivicCounter[getID()] = 0;
+ kLoopPlayer.m_aiBonusTradeCounter[getID()] = 0;
+ kLoopPlayer.m_aiPeacetimeTradeValue[getID()] = 0;
+ kLoopPlayer.m_aiPeacetimeGrantValue[getID()] = 0;
+ kLoopPlayer.m_aiGoldTradedTo[getID()] = 0;
+ kLoopPlayer.m_aiAttitudeExtra[getID()] = 0;
+ kLoopPlayer.m_abFirstContact[getID()] = false;
+ for (int iJ = 0; iJ < NUM_CONTACT_TYPES; iJ++)
+ {
+ kLoopPlayer.m_aaiContactTimer[getID()][iJ] = 0;
+ }
+ for (int iJ = 0; iJ < NUM_MEMORY_TYPES; iJ++)
+ {
+ kLoopPlayer.m_aaiMemoryCount[getID()][iJ] = 0;
+ }
+ }
+ }
+
+ for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
+ {
+ m_aiAverageYieldMultiplier[iI] = 0;
+ }
+ for (iI = 0; iI< NUM_COMMERCE_TYPES; iI++)
+ {
+ m_aiAverageCommerceMultiplier[iI] = 0;
+ m_aiAverageCommerceExchange[iI] = 0;
+ }
+ m_iAverageGreatPeopleMultiplier = 0;
+ m_iAveragesCacheTurn = -1;
+
+ m_iStrategyHash = 0;
+ m_iStrategyHashCacheTurn = -1;
+
+ m_bWasFinancialTrouble = false;
+ m_iTurnLastProductionDirty = -1;
+
+ m_iUpgradeUnitsCacheTurn = -1;
+ m_iUpgradeUnitsCachedExpThreshold = 0;
+ m_iUpgradeUnitsCachedGold = 0;
+
+ m_aiAICitySites.clear();
+
+ FAssert(m_aiBonusValue == NULL);
+ m_aiBonusValue = new int[GC.getNumBonusInfos()];
+ for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
+ {
+ m_aiBonusValue[iI] = -1;
+ }
+
+ FAssert(m_aiUnitClassWeights == NULL);
+ m_aiUnitClassWeights = new int[GC.getNumUnitClassInfos()];
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ m_aiUnitClassWeights[iI] = 0;
+ }
+
+ FAssert(m_aiUnitCombatWeights == NULL);
+ m_aiUnitCombatWeights = new int[GC.getNumUnitCombatInfos()];
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); iI++)
+ {
+ m_aiUnitCombatWeights[iI] = 0;
+ }
+
+ for (iI = 0; iI < MAX_PLAYERS; iI++)
+ {
+ m_aiCloseBordersAttitudeCache[iI] = 0;
+
+ if (!bConstructor && getID() != NO_PLAYER)
+ {
+ GET_PLAYER((PlayerTypes) iI).m_aiCloseBordersAttitudeCache[getID()] = 0;
+ }
+ }
+}
+
+
+int CvPlayerAI::AI_getFlavorValue(FlavorTypes eFlavor) const
+{
+ FAssertMsg((getPersonalityType() >= 0), "getPersonalityType() is less than zero");
+ FAssertMsg((eFlavor >= 0), "eFlavor is less than zero");
+ return GC.getLeaderHeadInfo(getPersonalityType()).getFlavorValue(eFlavor);
+}
+
+
+void CvPlayerAI::AI_doTurnPre()
+{
+ PROFILE_FUNC();
+
+ FAssertMsg(getPersonalityType() != NO_LEADER, "getPersonalityType() is not expected to be equal with NO_LEADER");
+ FAssertMsg(getLeaderType() != NO_LEADER, "getLeaderType() is not expected to be equal with NO_LEADER");
+ FAssertMsg(getCivilizationType() != NO_CIVILIZATION, "getCivilizationType() is not expected to be equal with NO_CIVILIZATION");
+
+ AI_invalidateCloseBordersAttitudeCache();
+
+ AI_doCounter();
+
+ AI_updateBonusValue();
+
+ AI_doEnemyUnitData();
+
+ if (isHuman())
+ {
+ return;
+ }
+
+ AI_doResearch();
+
+ AI_doCommerce();
+
+ AI_doMilitary();
+
+ AI_doCivics();
+
+ AI_doReligion();
+
+ AI_doCheckFinancialTrouble();
+
+ if (isBarbarian())
+ {
+ return;
+ }
+
+ if (isMinorCiv())
+ {
+ return;
+ }
+}
+
+
+void CvPlayerAI::AI_doTurnPost()
+{
+ PROFILE_FUNC();
+
+ if (isHuman())
+ {
+ return;
+ }
+
+ if (isBarbarian())
+ {
+ return;
+ }
+
+ if (isMinorCiv())
+ {
+ return;
+ }
+
+ AI_doDiplo();
+
+ AI_doSplit();
+
+
+ for (int i = 0; i < GC.getNumVictoryInfos(); ++i)
+ {
+ AI_launch((VictoryTypes)i);
+ }
+}
+
+
+void CvPlayerAI::AI_doTurnUnitsPre()
+{
+ PROFILE_FUNC();
+
+ AI_updateFoundValues();
+
+ if (GC.getGameINLINE().getSorenRandNum(8, "AI Update Area Targets") == 0) // XXX personality???
+ {
+ AI_updateAreaTargets();
+ }
+
+ if (isHuman())
+ {
+ return;
+ }
+
+ if (isBarbarian())
+ {
+ return;
+ }
+
+// if (AI_isDoStrategy(AI_STRATEGY_CRUSH))
+// {
+// AI_convertUnitAITypesForCrush();
+// }
+}
+
+
+void CvPlayerAI::AI_doTurnUnitsPost()
+{
+ PROFILE_FUNC();
+
+ CvUnit* pLoopUnit;
+ CvPlot* pUnitPlot;
+ bool bValid;
+ int iPass;
+ int iLoop;
+
+ if (!isHuman() || isOption(PLAYEROPTION_AUTO_PROMOTION))
+ {
+ for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
+ {
+ pLoopUnit->AI_promote();
+ }
+ }
+
+ if (isHuman())
+ {
+ return;
+ }
+
+ CvPlot* pLastUpgradePlot = NULL;
+ for (iPass = 0; iPass < 4; iPass++)
+ {
+ for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
+ {
+ bool bNoDisband = false;
+ bValid = false;
+
+ switch (iPass)
+ {
+ case 0:
+ if (AI_unitImpassableCount(pLoopUnit->getUnitType()) > 0)
+ {
+ bValid = true;
+ }
+ break;
+ case 1:
+ pUnitPlot = pLoopUnit->plot();
+ if (pUnitPlot->isCity())
+ {
+ if (pUnitPlot->getBestDefender(getID()) == pLoopUnit)
+ {
+ bNoDisband = true;
+ bValid = true;
+ pLastUpgradePlot = pUnitPlot;
+ }
+
+ // try to upgrade units which are in danger... but don't get obsessed
+ if (!bValid && (pLastUpgradePlot != pUnitPlot) && ((AI_getPlotDanger(pUnitPlot, 1, false)) > 0))
+ {
+ bNoDisband = true;
+ bValid = true;
+ pLastUpgradePlot = pUnitPlot;
+ }
+ }
+ break;
+ case 2:
+ if (pLoopUnit->cargoSpace() > 0)
+ {
+ bValid = true;
+ }
+ break;
+ case 3:
+ bValid = true;
+ break;
+ default:
+ FAssert(false);
+ break;
+ }
+
+ if (bValid)
+ {
+ bool bKilled = false;
+ if (!bNoDisband)
+ {
+ if (pLoopUnit->canFight())
+ {
+ int iExp = pLoopUnit->getExperience();
+ CvCity* pPlotCity = pLoopUnit->plot()->getPlotCity();
+ if (pPlotCity != NULL && pPlotCity->getOwnerINLINE() == getID())
+ {
+ int iCityExp = 0;
+ iCityExp += pPlotCity->getFreeExperience();
+ iCityExp += pPlotCity->getDomainFreeExperience(pLoopUnit->getDomainType());
+ iCityExp += pPlotCity->getUnitCombatFreeExperience(pLoopUnit->getUnitCombatType());
+ if (iCityExp > 0)
+ {
+ if ((iExp == 0) || (iExp < (iCityExp + 1) / 2))
+ {
+ if ((calculateUnitCost() > 0) && (AI_getPlotDanger( pLoopUnit->plot(), 2, false) == 0))
+ {
+ if ((pLoopUnit->getDomainType() != DOMAIN_LAND) || pLoopUnit->plot()->plotCount(PUF_isMilitaryHappiness, -1, -1, getID()) > 1)
+ {
+ pLoopUnit->kill(false);
+ bKilled = true;
+ pLastUpgradePlot = NULL;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (!bKilled)
+ {
+ pLoopUnit->AI_upgrade(); // CAN DELETE UNIT!!!
+ }
+ }
+ }
+ }
+
+ if (isBarbarian())
+ {
+ return;
+ }
+}
+
+
+void CvPlayerAI::AI_doPeace()
+{
+ PROFILE_FUNC();
+
+ CvDiploParameters* pDiplo;
+ CvCity* pBestReceiveCity;
+ CvCity* pBestGiveCity;
+ CvCity* pLoopCity;
+ CLinkList ourList;
+ CLinkList theirList;
+ bool abContacted[MAX_TEAMS];
+ TradeData item;
+ TechTypes eBestReceiveTech;
+ TechTypes eBestGiveTech;
+ int iReceiveGold;
+ int iGiveGold;
+ int iGold;
+ int iValue;
+ int iBestValue;
+ int iOurValue;
+ int iTheirValue;
+ int iLoop;
+ int iI, iJ;
+
+ FAssert(!isHuman());
+ FAssert(!isMinorCiv());
+ FAssert(!isBarbarian());
+
+ for (iI = 0; iI < MAX_TEAMS; iI++)
+ {
+ abContacted[iI] = false;
+ }
+
+ for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isAlive())
+ {
+ if (iI != getID())
+ {
+ if (canContact((PlayerTypes)iI) && AI_isWillingToTalk((PlayerTypes)iI))
+ {
+ if (!(GET_TEAM(getTeam()).isHuman()) && (GET_PLAYER((PlayerTypes)iI).isHuman() || !(GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isHuman())))
+ {
+ if (GET_TEAM(getTeam()).isAtWar(GET_PLAYER((PlayerTypes)iI).getTeam()))
+ {
+ if (!(GET_PLAYER((PlayerTypes)iI).isHuman()) || (GET_TEAM(getTeam()).getLeaderID() == getID()))
+ {
+ FAssertMsg(!(GET_PLAYER((PlayerTypes)iI).isBarbarian()), "(GET_PLAYER((PlayerTypes)iI).isBarbarian()) did not return false as expected");
+ FAssertMsg(iI != getID(), "iI is not expected to be equal with getID()");
+ FAssert(GET_PLAYER((PlayerTypes)iI).getTeam() != getTeam());
+
+ if (GET_TEAM(getTeam()).AI_getAtWarCounter(GET_PLAYER((PlayerTypes)iI).getTeam()) > 10)
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_PEACE_TREATY) == 0)
+ {
+ bool bOffered = false;
+
+ setTradeItem(&item, TRADE_SURRENDER);
+
+ if (canTradeItem((PlayerTypes)iI, item, true))
+ {
+ ourList.clear();
+ theirList.clear();
+
+ ourList.insertAtEnd(item);
+
+ bOffered = true;
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_PEACE_TREATY, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_PEACE_TREATY));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_OFFER_PEACE"));
+ pDiplo->setAIContact(true);
+ pDiplo->setOurOfferList(theirList);
+ pDiplo->setTheirOfferList(ourList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ else
+ {
+ GC.getGameINLINE().implementDeal(getID(), ((PlayerTypes)iI), &ourList, &theirList);
+ }
+ }
+
+ if (!bOffered)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_PEACE_TREATY), "AI Diplo Peace Treaty") == 0)
+ {
+ setTradeItem(&item, TRADE_PEACE_TREATY);
+
+ if (canTradeItem(((PlayerTypes)iI), item, true) && GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true))
+ {
+ iOurValue = GET_TEAM(getTeam()).AI_endWarVal(GET_PLAYER((PlayerTypes)iI).getTeam());
+ iTheirValue = GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).AI_endWarVal(getTeam());
+
+ eBestReceiveTech = NO_TECH;
+ eBestGiveTech = NO_TECH;
+
+ iReceiveGold = 0;
+ iGiveGold = 0;
+
+ pBestReceiveCity = NULL;
+ pBestGiveCity = NULL;
+
+ if (iTheirValue > iOurValue)
+ {
+ if (iTheirValue > iOurValue)
+ {
+ iBestValue = 0;
+
+ for (iJ = 0; iJ < GC.getNumTechInfos(); iJ++)
+ {
+ setTradeItem(&item, TRADE_TECHNOLOGIES, iJ);
+
+ if (GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true))
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "AI Peace Trading (Tech #1)"));
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestReceiveTech = ((TechTypes)iJ);
+ }
+ }
+ }
+
+ if (eBestReceiveTech != NO_TECH)
+ {
+ iOurValue += GET_TEAM(getTeam()).AI_techTradeVal(eBestReceiveTech, GET_PLAYER((PlayerTypes)iI).getTeam());
+ }
+ }
+
+ iGold = std::min((iTheirValue - iOurValue), GET_PLAYER((PlayerTypes)iI).AI_maxGoldTrade(getID()));
+
+ if (iGold > 0)
+ {
+ setTradeItem(&item, TRADE_GOLD, iGold);
+
+ if (GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true))
+ {
+ iReceiveGold = iGold;
+ iOurValue += iGold;
+ }
+ }
+
+ if (iTheirValue > iOurValue)
+ {
+ iBestValue = 0;
+
+ for (pLoopCity = GET_PLAYER((PlayerTypes)iI).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER((PlayerTypes)iI).nextCity(&iLoop))
+ {
+ setTradeItem(&item, TRADE_CITIES, pLoopCity->getID());
+
+ if (GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true))
+ {
+ iValue = pLoopCity->plot()->calculateCulturePercent(getID());
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ pBestReceiveCity = pLoopCity;
+ }
+ }
+ }
+
+ if (pBestReceiveCity != NULL)
+ {
+ iOurValue += AI_cityTradeVal(pBestReceiveCity);
+ }
+ }
+ }
+ else if (iOurValue > iTheirValue)
+ {
+ iBestValue = 0;
+
+ for (iJ = 0; iJ < GC.getNumTechInfos(); iJ++)
+ {
+ setTradeItem(&item, TRADE_TECHNOLOGIES, iJ);
+
+ if (canTradeItem(((PlayerTypes)iI), item, true))
+ {
+ if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).AI_techTradeVal((TechTypes)iJ, getTeam()) <= (iOurValue - iTheirValue))
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "AI Peace Trading (Tech #2)"));
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestGiveTech = ((TechTypes)iJ);
+ }
+ }
+ }
+ }
+
+ if (eBestGiveTech != NO_TECH)
+ {
+ iTheirValue += GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).AI_techTradeVal(eBestGiveTech, getTeam());
+ }
+
+ iGold = std::min((iOurValue - iTheirValue), AI_maxGoldTrade((PlayerTypes)iI));
+
+ if (iGold > 0)
+ {
+ setTradeItem(&item, TRADE_GOLD, iGold);
+
+ if (canTradeItem(((PlayerTypes)iI), item, true))
+ {
+ iGiveGold = iGold;
+ iTheirValue += iGold;
+ }
+ }
+
+ iBestValue = 0;
+
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ setTradeItem(&item, TRADE_CITIES, pLoopCity->getID());
+
+ if (canTradeItem(((PlayerTypes)iI), item, true))
+ {
+ if (GET_PLAYER((PlayerTypes)iI).AI_cityTradeVal(pLoopCity) <= (iOurValue - iTheirValue))
+ {
+ iValue = pLoopCity->plot()->calculateCulturePercent((PlayerTypes)iI);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ pBestGiveCity = pLoopCity;
+ }
+ }
+ }
+ }
+
+ if (pBestGiveCity != NULL)
+ {
+ iTheirValue += GET_PLAYER((PlayerTypes)iI).AI_cityTradeVal(pBestGiveCity);
+ }
+ }
+
+ if ((GET_PLAYER((PlayerTypes)iI).isHuman()) ? (iOurValue >= iTheirValue) : ((iOurValue > ((iTheirValue * 3) / 5)) && (iTheirValue > ((iOurValue * 3) / 5))))
+ {
+ ourList.clear();
+ theirList.clear();
+
+ setTradeItem(&item, TRADE_PEACE_TREATY);
+
+ ourList.insertAtEnd(item);
+ theirList.insertAtEnd(item);
+
+ if (eBestGiveTech != NO_TECH)
+ {
+ setTradeItem(&item, TRADE_TECHNOLOGIES, eBestGiveTech);
+ ourList.insertAtEnd(item);
+ }
+
+ if (eBestReceiveTech != NO_TECH)
+ {
+ setTradeItem(&item, TRADE_TECHNOLOGIES, eBestReceiveTech);
+ theirList.insertAtEnd(item);
+ }
+
+ if (iGiveGold != 0)
+ {
+ setTradeItem(&item, TRADE_GOLD, iGiveGold);
+ ourList.insertAtEnd(item);
+ }
+
+ if (iReceiveGold != 0)
+ {
+ setTradeItem(&item, TRADE_GOLD, iReceiveGold);
+ theirList.insertAtEnd(item);
+ }
+
+ if (pBestGiveCity != NULL)
+ {
+ setTradeItem(&item, TRADE_CITIES, pBestGiveCity->getID());
+ ourList.insertAtEnd(item);
+ }
+
+ if (pBestReceiveCity != NULL)
+ {
+ setTradeItem(&item, TRADE_CITIES, pBestReceiveCity->getID());
+ theirList.insertAtEnd(item);
+ }
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_PEACE_TREATY, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_PEACE_TREATY));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_OFFER_PEACE"));
+ pDiplo->setAIContact(true);
+ pDiplo->setOurOfferList(theirList);
+ pDiplo->setTheirOfferList(ourList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ else
+ {
+ GC.getGameINLINE().implementDeal(getID(), ((PlayerTypes)iI), &ourList, &theirList);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void CvPlayerAI::AI_updateFoundValues(bool bStartingLoc) const
+{
+ PROFILE_FUNC();
+
+ CvArea* pLoopArea;
+ CvPlot* pLoopPlot;
+ int iValue;
+ int iLoop;
+ int iI;
+ bool bCitySiteCalculations = (GC.getGame().getGameTurn() > GC.getGame().getStartTurn());
+
+
+ for(pLoopArea = GC.getMapINLINE().firstArea(&iLoop); pLoopArea != NULL; pLoopArea = GC.getMapINLINE().nextArea(&iLoop))
+ {
+ pLoopArea->setBestFoundValue(getID(), 0);
+ }
+
+ if (bStartingLoc)
+ {
+ for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
+ {
+ GC.getMapINLINE().plotByIndexINLINE(iI)->setFoundValue(getID(), -1);
+ }
+ }
+ else
+ {
+ if (!isBarbarian())
+ {
+ AI_invalidateCitySites(AI_getMinFoundValue());
+ }
+ for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
+ {
+ pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
+
+ if (pLoopPlot->isRevealed(getTeam(), false))// || AI_isPrimaryArea(pLoopPlot->area()))
+ {
+ long lResult=-1;
+ if(GC.getUSE_GET_CITY_FOUND_VALUE_CALLBACK())
+ {
+ CyArgsList argsList;
+ argsList.add((int)getID());
+ argsList.add(pLoopPlot->getX());
+ argsList.add(pLoopPlot->getY());
+ gDLL->getPythonIFace()->callFunction(PYGameModule, "getCityFoundValue", argsList.makeFunctionArgs(), &lResult);
+ }
+
+ if (lResult == -1)
+ {
+ iValue = AI_foundValue(pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE());
+ }
+ else
+ {
+ iValue = lResult;
+ }
+
+ pLoopPlot->setFoundValue(getID(), iValue);
+
+ if (iValue > pLoopPlot->area()->getBestFoundValue(getID()))
+ {
+ pLoopPlot->area()->setBestFoundValue(getID(), iValue);
+ }
+ }
+ }
+ if (!isBarbarian())
+ {
+ int iMaxCityCount = 4;
+ AI_updateCitySites(AI_getMinFoundValue(), iMaxCityCount);
+ }
+ }
+}
+
+
+void CvPlayerAI::AI_updateAreaTargets()
+{
+ CvArea* pLoopArea;
+ int iLoop;
+
+ for(pLoopArea = GC.getMapINLINE().firstArea(&iLoop); pLoopArea != NULL; pLoopArea = GC.getMapINLINE().nextArea(&iLoop))
+ {
+ if (!(pLoopArea->isWater()))
+ {
+ if (GC.getGameINLINE().getSorenRandNum(3, "AI Target City") == 0)
+ {
+ pLoopArea->setTargetCity(getID(), NULL);
+ }
+ else
+ {
+ pLoopArea->setTargetCity(getID(), AI_findTargetCity(pLoopArea));
+ }
+ }
+ }
+}
+
+
+// Returns priority for unit movement (lower values move first...)
+int CvPlayerAI::AI_movementPriority(CvSelectionGroup* pGroup) const
+{
+ CvUnit* pHeadUnit;
+ int iCurrCombat;
+ int iBestCombat;
+
+ pHeadUnit = pGroup->getHeadUnit();
+
+ if (pHeadUnit != NULL)
+ {
+ if (pHeadUnit->hasCargo())
+ {
+ if (pHeadUnit->specialCargo() == NO_SPECIALUNIT)
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+
+ if (pHeadUnit->getDomainType() == DOMAIN_AIR)
+ {
+ return 2;
+ }
+
+ if ((pHeadUnit->AI_getUnitAIType() == UNITAI_WORKER) || (pHeadUnit->AI_getUnitAIType() == UNITAI_WORKER_SEA))
+ {
+ return 3;
+ }
+
+ if ((pHeadUnit->AI_getUnitAIType() == UNITAI_EXPLORE) || (pHeadUnit->AI_getUnitAIType() == UNITAI_EXPLORE_SEA))
+ {
+ return 4;
+ }
+
+ if (pHeadUnit->bombardRate() > 0)
+ {
+ return 5;
+ }
+
+ if (pHeadUnit->collateralDamage() > 0)
+ {
+ return 6;
+ }
+
+ if (pHeadUnit->canFight())
+ {
+ if (pHeadUnit->withdrawalProbability() > 20)
+ {
+ return 7;
+ }
+
+ if (pHeadUnit->withdrawalProbability() > 0)
+ {
+ return 8;
+ }
+
+ iCurrCombat = pHeadUnit->currCombatStr(NULL, NULL);
+ iBestCombat = (GC.getGameINLINE().getBestLandUnitCombat() * 100);
+
+ if (pHeadUnit->noDefensiveBonus())
+ {
+ iCurrCombat *= 3;
+ iCurrCombat /= 2;
+ }
+
+ if (pHeadUnit->AI_isCityAIType())
+ {
+ iCurrCombat /= 2;
+ }
+
+ if (iCurrCombat > iBestCombat)
+ {
+ return 9;
+ }
+ else if (iCurrCombat > ((iBestCombat * 4) / 5))
+ {
+ return 10;
+ }
+ else if (iCurrCombat > ((iBestCombat * 3) / 5))
+ {
+ return 11;
+ }
+ else if (iCurrCombat > ((iBestCombat * 2) / 5))
+ {
+ return 12;
+ }
+ else if (iCurrCombat > ((iBestCombat * 1) / 5))
+ {
+ return 13;
+ }
+ else
+ {
+ return 14;
+ }
+ }
+
+ return 15;
+ }
+
+ return 16;
+}
+
+
+void CvPlayerAI::AI_unitUpdate()
+{
+ PROFILE_FUNC();
+
+ CLLNode* pCurrUnitNode;
+ CvSelectionGroup* pLoopSelectionGroup;
+ CLinkList tempGroupCycle;
+ CLinkList finalGroupCycle;
+ int iValue;
+
+ if (!hasBusyUnit())
+ {
+ pCurrUnitNode = headGroupCycleNode();
+
+ while (pCurrUnitNode != NULL)
+ {
+ pLoopSelectionGroup = getSelectionGroup(pCurrUnitNode->m_data);
+ pCurrUnitNode = nextGroupCycleNode(pCurrUnitNode);
+
+ if (pLoopSelectionGroup->AI_isForceSeparate())
+ {
+ // do not split groups that are in the midst of attacking
+ if (pLoopSelectionGroup->isForceUpdate() || !pLoopSelectionGroup->AI_isGroupAttack())
+ {
+ pLoopSelectionGroup->AI_separate(); // pointers could become invalid...
+ }
+ }
+ }
+
+ if (isHuman())
+ {
+ pCurrUnitNode = headGroupCycleNode();
+
+ while (pCurrUnitNode != NULL)
+ {
+ pLoopSelectionGroup = getSelectionGroup(pCurrUnitNode->m_data);
+ pCurrUnitNode = nextGroupCycleNode(pCurrUnitNode);
+
+ if (pLoopSelectionGroup->AI_update())
+ {
+ break; // pointers could become invalid...
+ }
+ }
+ }
+ else
+ {
+ tempGroupCycle.clear();
+ finalGroupCycle.clear();
+
+ pCurrUnitNode = headGroupCycleNode();
+
+ while (pCurrUnitNode != NULL)
+ {
+ tempGroupCycle.insertAtEnd(pCurrUnitNode->m_data);
+ pCurrUnitNode = nextGroupCycleNode(pCurrUnitNode);
+ }
+
+ iValue = 0;
+
+ while (tempGroupCycle.getLength() > 0)
+ {
+ pCurrUnitNode = tempGroupCycle.head();
+
+ while (pCurrUnitNode != NULL)
+ {
+ pLoopSelectionGroup = getSelectionGroup(pCurrUnitNode->m_data);
+ FAssertMsg(pLoopSelectionGroup != NULL, "selection group node with NULL selection group");
+
+ if (AI_movementPriority(pLoopSelectionGroup) <= iValue)
+ {
+ finalGroupCycle.insertAtEnd(pCurrUnitNode->m_data);
+ pCurrUnitNode = tempGroupCycle.deleteNode(pCurrUnitNode);
+ }
+ else
+ {
+ pCurrUnitNode = tempGroupCycle.next(pCurrUnitNode);
+ }
+ }
+
+ iValue++;
+ }
+
+ pCurrUnitNode = finalGroupCycle.head();
+
+ while (pCurrUnitNode != NULL)
+ {
+ pLoopSelectionGroup = getSelectionGroup(pCurrUnitNode->m_data);
+
+ if (NULL != pLoopSelectionGroup) // group might have been killed by a previous group update
+ {
+ if (pLoopSelectionGroup->AI_update())
+ {
+ break; // pointers could become invalid...
+ }
+ }
+
+ pCurrUnitNode = finalGroupCycle.next(pCurrUnitNode);
+ }
+ }
+ }
+}
+
+
+void CvPlayerAI::AI_makeAssignWorkDirty()
+{
+ CvCity* pLoopCity;
+ int iLoop;
+
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ pLoopCity->AI_setAssignWorkDirty(true);
+ }
+}
+
+
+void CvPlayerAI::AI_assignWorkingPlots()
+{
+ CvCity* pLoopCity;
+ int iLoop;
+
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ pLoopCity->AI_assignWorkingPlots();
+ }
+}
+
+
+void CvPlayerAI::AI_updateAssignWork()
+{
+ CvCity* pLoopCity;
+ int iLoop;
+
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ pLoopCity->AI_updateAssignWork();
+ }
+}
+
+
+void CvPlayerAI::AI_makeProductionDirty()
+{
+ CvCity* pLoopCity;
+ int iLoop;
+
+ FAssertMsg(!isHuman(), "isHuman did not return false as expected");
+
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ pLoopCity->AI_setChooseProductionDirty(true);
+ }
+}
+
+
+void CvPlayerAI::AI_conquerCity(CvCity* pCity)
+{
+ CvCity* pNearestCity;
+ bool bRaze = false;
+ int iRazeValue;
+ int iI;
+
+ if (canRaze(pCity))
+ {
+ iRazeValue = 0;
+ if (GC.getGameINLINE().getElapsedGameTurns() > 20)
+ {
+ if (getNumCities() > 4)
+ {
+ if (!(pCity->isHolyCity()) && !(pCity->hasActiveWorldWonder()))
+ {
+ if (pCity->getPreviousOwner() != BARBARIAN_PLAYER)
+ {
+ pNearestCity = GC.getMapINLINE().findCity(pCity->getX_INLINE(), pCity->getY_INLINE(), NO_PLAYER, getTeam(), true, false, NO_TEAM, NO_DIRECTION, pCity);
+
+ if (pNearestCity == NULL)
+ {
+ if (pCity->getPreviousOwner() != NO_PLAYER)
+ {
+ if (GET_TEAM(GET_PLAYER(pCity->getPreviousOwner()).getTeam()).countNumCitiesByArea(pCity->area()) > 3)
+ {
+ iRazeValue += 30;
+ }
+ }
+ }
+ else
+ {
+ int iDistance = plotDistance(pCity->getX_INLINE(), pCity->getY_INLINE(), pNearestCity->getX_INLINE(), pNearestCity->getY_INLINE());
+ if ( iDistance > 12)
+ {
+ iRazeValue += iDistance * 2;
+ }
+ }
+ }
+
+
+ if (pCity->area()->getCitiesPerPlayer(getID()) > 0)
+ {
+ if (AI_isFinancialTrouble())
+ {
+ iRazeValue += (70 - 15 * pCity->getPopulation());
+ }
+ }
+
+ if (getStateReligion() != NO_RELIGION)
+ {
+ if (pCity->isHasReligion(getStateReligion()))
+ {
+ if (GET_TEAM(getTeam()).hasShrine(getStateReligion()))
+ {
+ iRazeValue -= 50;
+ }
+ else
+ {
+ iRazeValue -= 10;
+ }
+ }
+ }
+
+ int iCloseness = pCity->AI_playerCloseness(getID());
+ if (iCloseness > 0)
+ {
+ iRazeValue -= 25;
+ iRazeValue -= iCloseness * 2;
+ }
+ else
+ {
+ iRazeValue += 60;
+ }
+
+ if (pCity->area()->getCitiesPerPlayer(getID()) > 0)
+ {
+ if (pCity->getPreviousOwner() != BARBARIAN_PLAYER)
+ {
+ iRazeValue += GC.getLeaderHeadInfo(getPersonalityType()).getRazeCityProb();
+ }
+ }
+
+ if (iRazeValue > 0)
+ {
+ for (iI = 0; iI < GC.getNumTraitInfos(); iI++)
+ {
+ if (hasTrait((TraitTypes)iI))
+ {
+ iRazeValue *= (100 - (GC.getTraitInfo((TraitTypes)iI).getUpkeepModifier()));
+ iRazeValue /= 100;
+ }
+ }
+
+ if (GC.getGameINLINE().getSorenRandNum(100, "AI Raze City") < iRazeValue)
+ {
+ bRaze = true;
+ pCity->doTask(TASK_RAZE);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!bRaze)
+ {
+ CvEventReporter::getInstance().cityAcquiredAndKept(GC.getGameINLINE().getActivePlayer(), pCity);
+ }
+}
+
+
+bool CvPlayerAI::AI_acceptUnit(CvUnit* pUnit) const
+{
+ if (isHuman())
+ {
+ return true;
+ }
+
+ if (AI_isFinancialTrouble())
+ {
+ if (pUnit->AI_getUnitAIType() == UNITAI_WORKER)
+ {
+ if (AI_neededWorkers(pUnit->area()) > 0)
+ {
+ return true;
+ }
+ }
+
+ if (pUnit->AI_getUnitAIType() == UNITAI_WORKER_SEA)
+ {
+ return true;
+ }
+
+ if (pUnit->AI_getUnitAIType() == UNITAI_MISSIONARY)
+ {
+ return true; //XXX
+ }
+ return false;
+ }
+
+ return true;
+}
+
+
+bool CvPlayerAI::AI_captureUnit(UnitTypes eUnit, CvPlot* pPlot) const
+{
+ CvCity* pNearestCity;
+
+ FAssert(!isHuman());
+
+ if (pPlot->getTeam() == getTeam())
+ {
+ return true;
+ }
+
+ pNearestCity = GC.getMapINLINE().findCity(pPlot->getX_INLINE(), pPlot->getY_INLINE(), NO_PLAYER, getTeam());
+
+ if (pNearestCity != NULL)
+ {
+ if (plotDistance(pPlot->getX_INLINE(), pPlot->getY_INLINE(), pNearestCity->getX_INLINE(), pNearestCity->getY_INLINE()) <= 4)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+DomainTypes CvPlayerAI::AI_unitAIDomainType(UnitAITypes eUnitAI) const
+{
+ switch (eUnitAI)
+ {
+ case UNITAI_UNKNOWN:
+ return NO_DOMAIN;
+ break;
+
+ case UNITAI_ANIMAL:
+ case UNITAI_SETTLE:
+ case UNITAI_WORKER:
+ case UNITAI_ATTACK:
+ case UNITAI_ATTACK_CITY:
+ case UNITAI_COLLATERAL:
+ case UNITAI_PILLAGE:
+ case UNITAI_RESERVE:
+ case UNITAI_COUNTER:
+ case UNITAI_PARADROP:
+ case UNITAI_CITY_DEFENSE:
+ case UNITAI_CITY_COUNTER:
+ case UNITAI_CITY_SPECIAL:
+ case UNITAI_EXPLORE:
+ case UNITAI_MISSIONARY:
+ case UNITAI_PROPHET:
+ case UNITAI_ARTIST:
+ case UNITAI_SCIENTIST:
+ case UNITAI_GENERAL:
+ case UNITAI_MERCHANT:
+ case UNITAI_ENGINEER:
+ case UNITAI_SPY:
+ case UNITAI_ATTACK_CITY_LEMMING:
+ return DOMAIN_LAND;
+ break;
+
+ case UNITAI_ICBM:
+ return DOMAIN_IMMOBILE;
+ break;
+
+ case UNITAI_WORKER_SEA:
+ case UNITAI_ATTACK_SEA:
+ case UNITAI_RESERVE_SEA:
+ case UNITAI_ESCORT_SEA:
+ case UNITAI_EXPLORE_SEA:
+ case UNITAI_ASSAULT_SEA:
+ case UNITAI_SETTLER_SEA:
+ case UNITAI_MISSIONARY_SEA:
+ case UNITAI_SPY_SEA:
+ case UNITAI_CARRIER_SEA:
+ case UNITAI_MISSILE_CARRIER_SEA:
+ case UNITAI_PIRATE_SEA:
+ return DOMAIN_SEA;
+ break;
+
+ case UNITAI_ATTACK_AIR:
+ case UNITAI_DEFENSE_AIR:
+ case UNITAI_CARRIER_AIR:
+ case UNITAI_MISSILE_AIR:
+ return DOMAIN_AIR;
+ break;
+
+ default:
+ FAssert(false);
+ break;
+ }
+
+ return NO_DOMAIN;
+}
+
+
+int CvPlayerAI::AI_yieldWeight(YieldTypes eYield) const
+{
+ if (eYield == YIELD_PRODUCTION)
+ {
+ int iProductionModifier = 100 + (30 * std::max(0, GC.getGame().getCurrentEra() - 1) / std::max(1, (GC.getNumEraInfos() - 2)));
+ return (GC.getYieldInfo(eYield).getAIWeightPercent() * iProductionModifier) / 100;
+ }
+ return GC.getYieldInfo(eYield).getAIWeightPercent();
+}
+
+
+int CvPlayerAI::AI_commerceWeight(CommerceTypes eCommerce, CvCity* pCity) const
+{
+ int iWeight;
+
+ iWeight = GC.getCommerceInfo(eCommerce).getAIWeightPercent();
+
+ //sorry but the merchant descrimination must stop.
+ iWeight = std::min(110, iWeight);
+
+ //XXX Add something for 100%/0% type situations
+ switch (eCommerce)
+ {
+ case COMMERCE_RESEARCH:
+ if (AI_avoidScience())
+ {
+ if (isNoResearchAvailable())
+ {
+ iWeight = 0;
+ }
+ else
+ {
+ iWeight /= 8;
+ }
+ }
+ break;
+ case COMMERCE_GOLD:
+ if (getCommercePercent(COMMERCE_GOLD) == 100)
+ {
+ //avoid strikes
+ if (getGoldPerTurn() < 0)
+ {
+ iWeight += 15;
+ }
+ }
+ else if (getCommercePercent(COMMERCE_GOLD) == 0)
+ {
+ //put more money towards other commerce types
+ if (getGoldPerTurn() > 0)
+ {
+ iWeight -= 15;
+ }
+ }
+ break;
+ case COMMERCE_CULTURE:
+ // COMMERCE_CULTURE AIWeightPercent is 25% in default xml
+
+ if (pCity != NULL)
+ {
+ if (pCity->getCultureTimes100(getID()) >= 100 * GC.getGameINLINE().getCultureThreshold((CultureLevelTypes)(GC.getNumCultureLevelInfos() - 1)))
+ {
+ iWeight /= 50;
+ }
+ else if (AI_isDoStrategy(AI_STRATEGY_CULTURE3))
+ {
+ int iCultureRateRank = pCity->findCommerceRateRank(COMMERCE_CULTURE);
+ int iCulturalVictoryNumCultureCities = GC.getGameINLINE().culturalVictoryNumCultureCities();
+
+ // if one of the currently best cities, then focus hard, *4
+ if (iCultureRateRank <= iCulturalVictoryNumCultureCities)
+ {
+ iWeight *= 4;
+ }
+ // if one of the 3 close to the top, then still emphasize culture some, *2
+ else if (iCultureRateRank <= iCulturalVictoryNumCultureCities + 3)
+ {
+ iWeight *= 2;
+ }
+ }
+ else if (AI_isDoStrategy(AI_STRATEGY_CULTURE2))
+ {
+ iWeight *= 3;
+ }
+ else if (AI_isDoStrategy(AI_STRATEGY_CULTURE1))
+ {
+ iWeight *= 2;
+ }
+
+ iWeight += (100 - pCity->plot()->calculateCulturePercent(getID()));
+
+ if (pCity->getCultureLevel() <= (CultureLevelTypes) 1)
+ {
+ iWeight = std::max(iWeight, 800);
+ }
+ }
+ // pCity == NULL
+ else
+ {
+ if (AI_isDoStrategy(AI_STRATEGY_CULTURE3))
+ {
+ iWeight *= 3;
+ iWeight /= 4;
+ }
+ else if (AI_isDoStrategy(AI_STRATEGY_CULTURE2))
+ {
+ iWeight *= 2;
+ iWeight /= 3;
+ }
+ else if (AI_isDoStrategy(AI_STRATEGY_CULTURE1))
+ {
+ iWeight /= 2;
+ }
+ else
+ {
+ iWeight /= 3;
+ }
+ }
+ break;
+ case COMMERCE_ESPIONAGE:
+ {
+ int iEspMultiplier = 0;
+ for (int iTeam = 0; iTeam < MAX_CIV_TEAMS; ++iTeam)
+ {
+ CvTeam& kLoopTeam = GET_TEAM((TeamTypes)iTeam);
+ if (kLoopTeam.isAlive() && iTeam != getTeam() && !kLoopTeam.isVassal(getTeam()) && !GET_TEAM(getTeam()).isVassal((TeamTypes)iTeam))
+ {
+ int iPointDiff = kLoopTeam.getEspionagePointsAgainstTeam(getTeam()) - GET_TEAM(getTeam()).getEspionagePointsAgainstTeam((TeamTypes)iTeam);
+ if (iPointDiff > 0)
+ {
+ iEspMultiplier += 1;
+ break;
+ }
+ }
+ }
+ iEspMultiplier += (iEspMultiplier > 0) ? 3 : 0;
+ iWeight *= iEspMultiplier;
+ iWeight *= AI_getEspionageWeight();
+ iWeight /= 100;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return iWeight;
+}
+
+// Improved as per Blake - thanks!
+int CvPlayerAI::AI_foundValue(int iX, int iY, int iMinRivalRange, bool bStartingLoc) const
+{
+ CvCity* pNearestCity;
+ CvArea* pArea;
+ CvPlot* pPlot;
+ CvPlot* pLoopPlot;
+ FeatureTypes eFeature;
+ BonusTypes eBonus;
+ ImprovementTypes eBonusImprovement;
+ bool bHasGoodBonus;
+ int iOwnedTiles;
+ int iBadTile;
+ int iTakenTiles;
+ int iTeammateTakenTiles;
+ int iDifferentAreaTile;
+ int iTeamAreaCities;
+ int iHealth;
+ int iValue;
+ int iTempValue;
+ int iRange;
+ int iDX, iDY;
+ int iI;
+ bool bIsCoastal;
+ int iResourceValue = 0;
+ int iSpecialFood = 0;
+ int iSpecialFoodPlus = 0;
+ int iSpecialFoodMinus = 0;
+ int iSpecialProduction = 0;
+ int iSpecialCommerce = 0;
+
+ bool bNeutralTerritory = true;
+
+ int iGreed;
+ int iNumAreaCities;
+
+ pPlot = GC.getMapINLINE().plotINLINE(iX, iY);
+
+ if (!canFound(iX, iY))
+ {
+ return 0;
+ }
+
+ bIsCoastal = pPlot->isCoastalLand(GC.getMIN_WATER_SIZE_FOR_OCEAN());
+ pArea = pPlot->area();
+ iNumAreaCities = pArea->getCitiesPerPlayer(getID());
+
+ bool bAdvancedStart = (getAdvancedStartPoints() >= 0);
+
+ if (!bStartingLoc && !bAdvancedStart)
+ {
+ if (!bIsCoastal && iNumAreaCities == 0)
+ {
+ return 0;
+ }
+ }
+
+ if (bAdvancedStart)
+ {
+ //FAssert(!bStartingLoc);
+ FAssert(GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_START));
+ if (bStartingLoc)
+ {
+ bAdvancedStart = false;
+ }
+ }
+
+ //Explaination of city site adjustment:
+ //Any plot which is otherwise within the radius of a city site
+ //is basically treated as if it's within an existing city radius
+ std::vector abCitySiteRadius(NUM_CITY_PLOTS, false);
+
+ if (!bStartingLoc)
+ {
+ if (!AI_isPlotCitySite(pPlot))
+ {
+ for (iI = 0; iI < NUM_CITY_PLOTS; iI++)
+ {
+ pLoopPlot = plotCity(iX, iY, iI);
+ if (pLoopPlot != NULL)
+ {
+ for (int iJ = 0; iJ < AI_getNumCitySites(); iJ++)
+ {
+ CvPlot* pCitySitePlot = AI_getCitySite(iJ);
+ if (pCitySitePlot != pPlot)
+ {
+ if (plotDistance(pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), pCitySitePlot->getX_INLINE(), pCitySitePlot->getY_INLINE()) <= CITY_PLOTS_RADIUS)
+ {
+ //Plot is inside the radius of a city site
+ abCitySiteRadius[iI] = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ std::vector paiBonusCount;
+
+ for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
+ {
+ paiBonusCount.push_back(0);
+ }
+
+ if (iMinRivalRange != -1)
+ {
+ for (iDX = -(iMinRivalRange); iDX <= iMinRivalRange; iDX++)
+ {
+ for (iDY = -(iMinRivalRange); iDY <= iMinRivalRange; iDY++)
+ {
+ pLoopPlot = plotXY(iX, iY, iDX, iDY);
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->plotCheck(PUF_isOtherTeam, getID()) != NULL)
+ {
+ return 0;
+ }
+ }
+ }
+ }
+ }
+
+ if (bStartingLoc)
+ {
+ if (pPlot->isGoody())
+ {
+ return 0;
+ }
+
+ for (iI = 0; iI < NUM_CITY_PLOTS; iI++)
+ {
+ pLoopPlot = plotCity(iX, iY, iI);
+
+ if (pLoopPlot == NULL)
+ {
+ return 0;
+ }
+ }
+ }
+
+ iOwnedTiles = 0;
+
+ for (iI = 0; iI < NUM_CITY_PLOTS; iI++)
+ {
+ pLoopPlot = plotCity(iX, iY, iI);
+
+ if (pLoopPlot == NULL)
+ {
+ iOwnedTiles++;
+ }
+ else if (pLoopPlot->isOwned())
+ {
+ if (pLoopPlot->getTeam() != getTeam())
+ {
+ iOwnedTiles++;
+ }
+ }
+ }
+
+ if (iOwnedTiles > (NUM_CITY_PLOTS / 3))
+ {
+ return 0;
+ }
+
+ iBadTile = 0;
+
+ for (iI = 0; iI < NUM_CITY_PLOTS; iI++)
+ {
+ pLoopPlot = plotCity(iX, iY, iI);
+
+ if (iI != CITY_HOME_PLOT)
+ {
+ if ((pLoopPlot == NULL) || pLoopPlot->isImpassable())
+ {
+ iBadTile += 2;
+ }
+ else if (!(pLoopPlot->isFreshWater()) && !(pLoopPlot->isHills()))
+ {
+ if ((pLoopPlot->calculateBestNatureYield(YIELD_FOOD, getTeam()) == 0) || (pLoopPlot->calculateTotalBestNatureYield(getTeam()) <= 1))
+ {
+ iBadTile += 2;
+ }
+ else if (pLoopPlot->isWater() && !bIsCoastal && (pLoopPlot->calculateBestNatureYield(YIELD_FOOD, getTeam()) <= 1))
+ {
+ iBadTile++;
+ }
+ }
+ else if (pLoopPlot->isOwned())
+ {
+ if (pLoopPlot->getTeam() == getTeam())
+ {
+ if (pLoopPlot->isCityRadius() || abCitySiteRadius[iI])
+ {
+ iBadTile += bAdvancedStart ? 2 : 1;
+ }
+ }
+ }
+ }
+ }
+
+ iBadTile /= 2;
+
+ if (!bStartingLoc)
+ {
+ if ((iBadTile > (NUM_CITY_PLOTS / 2)) || (pArea->getNumTiles() <= 2))
+ {
+ bHasGoodBonus = false;
+
+ for (iI = 0; iI < NUM_CITY_PLOTS; iI++)
+ {
+ pLoopPlot = plotCity(iX, iY, iI);
+
+ if (pLoopPlot != NULL)
+ {
+ if (!(pLoopPlot->isOwned()))
+ {
+ if (pLoopPlot->isWater() || (pLoopPlot->area() == pArea) || (pLoopPlot->area()->getCitiesPerPlayer(getID()) > 0))
+ {
+ eBonus = pLoopPlot->getBonusType(getTeam());
+
+ if (eBonus != NO_BONUS)
+ {
+ if ((getNumTradeableBonuses(eBonus) == 0) || (AI_bonusVal(eBonus) > 10)
+ || (GC.getBonusInfo(eBonus).getYieldChange(YIELD_FOOD) > 0))
+ {
+ bHasGoodBonus = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!bHasGoodBonus)
+ {
+ return 0;
+ }
+ }
+ }
+
+ iTakenTiles = 0;
+ iTeammateTakenTiles = 0;
+ iHealth = 0;
+ iValue = 1000;
+
+ iGreed = 100;
+
+ if (bAdvancedStart)
+ {
+ iGreed = 150;
+ }
+ else if (!bStartingLoc)
+ {
+ for (iI = 0; iI < GC.getNumTraitInfos(); iI++)
+ {
+ if (hasTrait((TraitTypes)iI))
+ {
+ //Greedy founding means getting the best possible sites - fitting maximum
+ //resources into the fat cross.
+ iGreed += (GC.getTraitInfo((TraitTypes)iI).getUpkeepModifier() / 2);
+ iGreed += 20 * (GC.getTraitInfo((TraitTypes)iI).getCommerceChange(COMMERCE_CULTURE));
+ }
+ }
+ }
+ //iClaimThreshold is the culture required to pop the 2nd borders.
+ int iClaimThreshold = GC.getGameINLINE().getCultureThreshold((CultureLevelTypes)(std::min(2, (GC.getNumCultureLevelInfos() - 1))));
+ iClaimThreshold = std::max(1, iClaimThreshold);
+ iClaimThreshold *= (std::max(100, iGreed));
+
+ int iYieldLostHere = 0;
+
+ for (iI = 0; iI < NUM_CITY_PLOTS; iI++)
+ {
+ pLoopPlot = plotCity(iX, iY, iI);
+
+ if (pLoopPlot == NULL)
+ {
+ iTakenTiles++;
+ }
+ else if (pLoopPlot->isCityRadius() || abCitySiteRadius[iI])
+ {
+ iTakenTiles++;
+
+ if (abCitySiteRadius[iI])
+ {
+ iTeammateTakenTiles++;
+ }
+ }
+ else
+ {
+ iTempValue = 0;
+
+ eFeature = pLoopPlot->getFeatureType();
+ eBonus = pLoopPlot->getBonusType((bStartingLoc) ? NO_TEAM : getTeam());
+ eBonusImprovement = NO_IMPROVEMENT;
+
+ int iCultureMultiplier;
+ if (!pLoopPlot->isOwned() || (pLoopPlot->getOwnerINLINE() == getID()))
+ {
+ iCultureMultiplier = 100;
+ }
+ else
+ {
+ bNeutralTerritory = false;
+ int iOurCulture = pLoopPlot->getCulture(getID());
+ int iOtherCulture = std::max(1, pLoopPlot->getCulture(pLoopPlot->getOwnerINLINE()));
+ iCultureMultiplier = 100 * (iOurCulture + iClaimThreshold);
+ iCultureMultiplier /= (iOtherCulture + iClaimThreshold);
+ iCultureMultiplier = std::min(100, iCultureMultiplier);
+ //The multiplier is basically normalized...
+ //100% means we own (or rightfully own) the tile.
+ //50% means the hostile culture is fairly firmly entrenched.
+ }
+
+ if (iCultureMultiplier < ((iNumAreaCities > 0) ? 25 : 50))
+ {
+ //discourage hopeless cases, especially on other continents.
+ iTakenTiles += (iNumAreaCities > 0) ? 1 : 2;
+ }
+
+ if (eBonus != NO_BONUS)
+ {
+ for (int iImprovement = 0; iImprovement < GC.getNumImprovementInfos(); ++iImprovement)
+ {
+ CvImprovementInfo& kImprovement = GC.getImprovementInfo((ImprovementTypes)iImprovement);
+
+ if (kImprovement.isImprovementBonusMakesValid(eBonus))
+ {
+ eBonusImprovement = (ImprovementTypes)iImprovement;
+ break;
+ }
+ }
+ }
+
+ int aiYield[NUM_YIELD_TYPES];
+
+ for (int iYieldType = 0; iYieldType < NUM_YIELD_TYPES; ++iYieldType)
+ {
+ YieldTypes eYield = (YieldTypes)iYieldType;
+ aiYield[eYield] = pLoopPlot->getYield(eYield);
+
+ if (iI == CITY_HOME_PLOT)
+ {
+ int iBasePlotYield = aiYield[eYield];
+ aiYield[eYield] += GC.getYieldInfo(eYield).getCityChange();
+
+ if (eFeature != NO_FEATURE)
+ {
+ aiYield[eYield] -= GC.getFeatureInfo(eFeature).getYieldChange(eYield);
+ iBasePlotYield = std::max(iBasePlotYield, aiYield[eYield]);
+ }
+
+ if (eBonus == NO_BONUS)
+ {
+ aiYield[eYield] = std::max(aiYield[eYield], GC.getYieldInfo(eYield).getMinCity());
+ }
+ else
+ {
+ int iBonusYieldChange = GC.getBonusInfo(eBonus).getYieldChange(eYield);
+ aiYield[eYield] += iBonusYieldChange;
+ iBasePlotYield += iBonusYieldChange;
+
+ aiYield[eYield] = std::max(aiYield[eYield], GC.getYieldInfo(eYield).getMinCity());
+ }
+
+ if (eBonusImprovement != NO_IMPROVEMENT)
+ {
+ iBasePlotYield += GC.getImprovementInfo(eBonusImprovement).getImprovementBonusYield(eBonus, eYield);
+
+ if (iBasePlotYield > aiYield[eYield])
+ {
+ aiYield[eYield] -= 2 * (iBasePlotYield - aiYield[eYield]);
+ }
+ else
+ {
+ aiYield[eYield] += aiYield[eYield] - iBasePlotYield;
+ }
+ }
+ }
+ }
+
+ if (iI == CITY_HOME_PLOT)
+ {
+ iTempValue += aiYield[YIELD_FOOD] * 60;
+ iTempValue += aiYield[YIELD_PRODUCTION] * 60;
+ iTempValue += aiYield[YIELD_COMMERCE] * 40;
+ }
+ else if (aiYield[YIELD_FOOD] >= GC.getFOOD_CONSUMPTION_PER_POPULATION())
+ {
+ iTempValue += aiYield[YIELD_FOOD] * 40;
+ iTempValue += aiYield[YIELD_PRODUCTION] * 40;
+ iTempValue += aiYield[YIELD_COMMERCE] * 30;
+
+ if (bStartingLoc)
+ {
+ iTempValue *= 2;
+ }
+ }
+ else if (aiYield[YIELD_FOOD] == GC.getFOOD_CONSUMPTION_PER_POPULATION() - 1)
+ {
+ iTempValue += aiYield[YIELD_FOOD] * 25;
+ iTempValue += aiYield[YIELD_PRODUCTION] * 25;
+ iTempValue += aiYield[YIELD_COMMERCE] * 20;
+ }
+ else
+ {
+ iTempValue += aiYield[YIELD_FOOD] * 15;
+ iTempValue += aiYield[YIELD_PRODUCTION] * 15;
+ iTempValue += aiYield[YIELD_COMMERCE] * 10;
+ }
+
+ if (pLoopPlot->isWater())
+ {
+ if (aiYield[YIELD_COMMERCE] > 1)
+ {
+ iTempValue += bIsCoastal ? 30 : -20;
+ if (bIsCoastal && (aiYield[YIELD_FOOD] >= GC.getFOOD_CONSUMPTION_PER_POPULATION()))
+ {
+ iSpecialFoodPlus += 1;
+ }
+ if (bStartingLoc && !pPlot->isStartingPlot())
+ {
+ // I'm pretty much forbidding starting 1 tile inland non-coastal.
+ // with more than a few coast tiles.
+ iTempValue += bIsCoastal ? 0 : -400;
+ }
+ }
+ }
+
+ if (pLoopPlot->isRiver())
+ {
+ iTempValue += 10;
+ }
+
+ if (iI == CITY_HOME_PLOT)
+ {
+ iTempValue *= 2;
+ }
+ else if ((pLoopPlot->getOwnerINLINE() == getID()) || (stepDistance(iX, iY, pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE()) == 1))
+ {
+ iTempValue *= 3;
+ iTempValue /= 2;
+ }
+ else
+ {
+ iTempValue *= iGreed;
+ iTempValue /= 100;
+ }
+
+ iTempValue *= iCultureMultiplier;
+ iTempValue /= 100;
+
+ iValue += iTempValue;
+
+ if (iCultureMultiplier > 33) //ignore hopelessly entrenched tiles.
+ {
+ if (eFeature != NO_FEATURE)
+ {
+ if (iI != CITY_HOME_PLOT)
+ {
+ iHealth += GC.getFeatureInfo(eFeature).getHealthPercent();
+
+ iSpecialFoodPlus += std::max(0, aiYield[YIELD_FOOD] - GC.getFOOD_CONSUMPTION_PER_POPULATION());
+ }
+ }
+
+ if ((eBonus != NO_BONUS) && ((pLoopPlot->area() == pPlot->area()) ||
+ (pLoopPlot->area()->getCitiesPerPlayer(getID()) > 0)))
+ {
+ paiBonusCount[eBonus]++;
+ FAssert(paiBonusCount[eBonus] > 0);
+
+ iTempValue = (AI_bonusVal(eBonus) * ((!bStartingLoc && (getNumTradeableBonuses(eBonus) == 0) && (paiBonusCount[eBonus] == 1)) ? 80 : 20));
+ iTempValue *= ((bStartingLoc) ? 100 : iGreed);
+ iTempValue /= 100;
+
+ if (iI != CITY_HOME_PLOT && !bStartingLoc)
+ {
+ if ((pLoopPlot->getOwnerINLINE() != getID()) && stepDistance(pPlot->getX_INLINE(),pPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE()) > 1)
+ {
+ iTempValue *= 2;
+ iTempValue /= 3;
+
+ iTempValue *= std::min(150, iGreed);
+ iTempValue /= 100;
+ }
+ }
+
+ iValue += (iTempValue + 10);
+
+ if (iI != CITY_HOME_PLOT)
+ {
+ if (eBonusImprovement != NO_IMPROVEMENT)
+ {
+ int iSpecialFoodTemp;
+ iSpecialFoodTemp = pLoopPlot->calculateBestNatureYield(YIELD_FOOD, getTeam()) + GC.getImprovementInfo(eBonusImprovement).getImprovementBonusYield(eBonus, YIELD_FOOD);
+
+ iSpecialFood += iSpecialFoodTemp;
+
+ iSpecialFoodTemp -= GC.getFOOD_CONSUMPTION_PER_POPULATION();
+
+ iSpecialFoodPlus += std::max(0,iSpecialFoodTemp);
+ iSpecialFoodMinus -= std::min(0,iSpecialFoodTemp);
+ iSpecialProduction += pLoopPlot->calculateBestNatureYield(YIELD_PRODUCTION, getTeam()) + GC.getImprovementInfo(eBonusImprovement).getImprovementBonusYield(eBonus, YIELD_PRODUCTION);
+ iSpecialCommerce += pLoopPlot->calculateBestNatureYield(YIELD_COMMERCE, getTeam()) + GC.getImprovementInfo(eBonusImprovement).getImprovementBonusYield(eBonus, YIELD_COMMERCE);
+ }
+
+ if (eFeature != NO_FEATURE)
+ {
+ if (GC.getFeatureInfo(eFeature).getYieldChange(YIELD_FOOD) < 0)
+ {
+ iResourceValue -= 30;
+ }
+ }
+
+ if (pLoopPlot->isWater())
+ {
+ iValue += (bIsCoastal ? 100 : -800);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ iResourceValue += iSpecialFood * 50;
+ iResourceValue += iSpecialProduction * 50;
+ iResourceValue += iSpecialCommerce * 50;
+ if (bStartingLoc)
+ {
+ iResourceValue /= 2;
+ }
+
+ iValue += std::max(0, iResourceValue);
+
+ if (iTakenTiles > (NUM_CITY_PLOTS / 3) && iResourceValue < 250)
+ {
+ return 0;
+ }
+
+ if (iTeammateTakenTiles > 1)
+ {
+ return 0;
+ }
+
+ iValue += (iHealth / 5);
+
+ if (bIsCoastal)
+ {
+ if (!bStartingLoc)
+ {
+ if (pArea->getCitiesPerPlayer(getID()) == 0)
+ {
+ if (bNeutralTerritory)
+ {
+ iValue += (iResourceValue > 0) ? 800 : 100;
+ }
+ }
+ else
+ {
+ iValue += 400;
+ }
+ }
+ else
+ {
+ //let other penalties bring this down.
+ iValue += 600;
+ if (!pPlot->isStartingPlot())
+ {
+ if (pArea->getNumStartingPlots() == 0)
+ {
+ iValue += 1000;
+ }
+ }
+ }
+ }
+
+ if (pPlot->isHills())
+ {
+ iValue += 200;
+ }
+
+ if (pPlot->isRiver())
+ {
+ iValue += 40;
+ }
+
+ if (pPlot->isFreshWater())
+ {
+ iValue += 40;
+ iValue += (GC.getDefineINT("FRESH_WATER_HEALTH_CHANGE") * 30);
+ }
+
+ if (bStartingLoc)
+ {
+ iRange = GREATER_FOUND_RANGE;
+ int iGreaterBadTile = 0;
+
+ for (iDX = -(iRange); iDX <= iRange; iDX++)
+ {
+ for (iDY = -(iRange); iDY <= iRange; iDY++)
+ {
+ pLoopPlot = plotXY(iX, iY, iDX, iDY);
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->isWater() || (pLoopPlot->area() == pArea))
+ {
+ if (plotDistance(iX, iY, pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE()) <= iRange)
+ {
+ iTempValue = 0;
+ iTempValue += (pLoopPlot->getYield(YIELD_FOOD) * 15);
+ iTempValue += (pLoopPlot->getYield(YIELD_PRODUCTION) * 11);
+ iTempValue += (pLoopPlot->getYield(YIELD_COMMERCE) * 5);
+ iValue += iTempValue;
+ if (iTempValue < 21)
+ {
+
+ iGreaterBadTile += 2;
+ if (pLoopPlot->getFeatureType() != NO_FEATURE)
+ {
+ if (pLoopPlot->calculateBestNatureYield(YIELD_FOOD,getTeam()) > 1)
+ {
+ iGreaterBadTile--;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!pPlot->isStartingPlot())
+ {
+ iGreaterBadTile /= 2;
+ if (iGreaterBadTile > 12)
+ {
+ iValue *= 11;
+ iValue /= iGreaterBadTile;
+ }
+ }
+
+ int iWaterCount = 0;
+
+ for (iI = 0; iI < NUM_CITY_PLOTS; iI++)
+ {
+ pLoopPlot = plotCity(iX, iY, iI);
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->isWater())
+ {
+ iWaterCount ++;
+ if (pLoopPlot->getYield(YIELD_FOOD) <= 1)
+ {
+ iWaterCount++;
+ }
+ }
+ }
+ }
+ iWaterCount /= 2;
+
+ int iLandCount = (NUM_CITY_PLOTS - iWaterCount);
+
+ if (iLandCount < (NUM_CITY_PLOTS / 2))
+ {
+ //discourage very water-heavy starts.
+ iValue *= 1 + iLandCount;
+ iValue /= (1 + (NUM_CITY_PLOTS / 2));
+ }
+ }
+
+ if (bStartingLoc)
+ {
+ if (pPlot->getMinOriginalStartDist() == -1)
+ {
+ iValue += (GC.getMapINLINE().maxStepDistance() * 100);
+ }
+ else
+ {
+ iValue *= (1 + 4 * pPlot->getMinOriginalStartDist());
+ iValue /= (1 + 2 * GC.getMapINLINE().maxStepDistance());
+ }
+
+ //nice hacky way to avoid this messing with normalizer, use elsewhere?
+ if (!pPlot->isStartingPlot())
+ {
+ int iMinDistanceFactor = MAX_INT;
+ int iMinRange = startingPlotRange();
+
+ iValue *= 100;
+ for (int iJ = 0; iJ < MAX_CIV_PLAYERS; iJ++)
+ {
+ if (GET_PLAYER((PlayerTypes)iJ).isAlive())
+ {
+ if (iJ != getID())
+ {
+ int iClosenessFactor = GET_PLAYER((PlayerTypes)iJ).startingPlotDistanceFactor(pPlot, getID(), iMinRange);
+ iMinDistanceFactor = std::min(iClosenessFactor, iMinDistanceFactor);
+
+ if (iClosenessFactor < 1000)
+ {
+ iValue *= 2000 + iClosenessFactor;
+ iValue /= 3000;
+ }
+ }
+ }
+ }
+
+ if (iMinDistanceFactor > 1000)
+ {
+ //give a maximum boost of 25% for somewhat distant locations, don't go overboard.
+ iMinDistanceFactor = std::min(1500, iMinDistanceFactor);
+ iValue *= (1000 + iMinDistanceFactor);
+ iValue /= 2000;
+ }
+ else if (iMinDistanceFactor < 1000)
+ {
+ //this is too close so penalize again.
+ iValue *= iMinDistanceFactor;
+ iValue /= 1000;
+ iValue *= iMinDistanceFactor;
+ iValue /= 1000;
+ }
+
+ iValue /= 10;
+
+ if (pPlot->getBonusType() != NO_BONUS)
+ {
+ iValue /= 2;
+ }
+ }
+ }
+
+ if (bAdvancedStart)
+ {
+ if (pPlot->getBonusType() != NO_BONUS)
+ {
+ iValue *= 70;
+ iValue /= 100;
+ }
+ }
+
+ pNearestCity = GC.getMapINLINE().findCity(iX, iY, ((isBarbarian()) ? NO_PLAYER : getID()));
+
+ if (pNearestCity != NULL)
+ {
+ if (isBarbarian())
+ {
+ iValue -= (std::max(0, (8 - plotDistance(iX, iY, pNearestCity->getX_INLINE(), pNearestCity->getY_INLINE()))) * 200);
+ }
+ else
+ {
+ int iDistance = plotDistance(iX, iY, pNearestCity->getX_INLINE(), pNearestCity->getY_INLINE());
+ int iNumCities = getNumCities();
+ if (iDistance > 5)
+ {
+ iValue -= (iDistance - 5) * 500;
+ }
+ else if (iDistance < 4)
+ {
+ iValue -= (4 - iDistance) * 2000;
+ }
+ iValue *= (8 + iNumCities * 4);
+ iValue /= (2 + (iNumCities * 4) + iDistance);
+ if (pNearestCity->isCapital())
+ {
+ iValue *= 150;
+ iValue /= 100;
+ }
+ else if (getCapitalCity() != NULL)
+ {
+ //Provide up to a 50% boost to value (80% for adv.start)
+ //for city sites which are relatively close to the core
+ //compared with the most distance city from the core
+ //(having a boost rather than distance penalty avoids some distortion)
+
+ //This is not primarly about maitenance but more about empire
+ //shape as such forbidden palace/state property are not big deal.
+ CvCity* pLoopCity;
+ int iLoop;
+ int iMaxDistanceFromCapital = 0;
+
+ int iCapitalX = getCapitalCity()->getX();
+ int iCapitalY = getCapitalCity()->getY();
+
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ iMaxDistanceFromCapital = std::max(iMaxDistanceFromCapital, plotDistance(iCapitalX, iCapitalY, pLoopCity->getX_INLINE(), pLoopCity->getY_INLINE()));
+ }
+
+ int iDistanceToCapital = plotDistance(iCapitalX, iCapitalY, iX, iY);
+
+ FAssert(iMaxDistanceFromCapital > 0);
+ iValue *= 100 + (((bAdvancedStart ? 80 : 50) * std::max(0, (iMaxDistanceFromCapital - iDistance))) / iMaxDistanceFromCapital);
+ iValue /= 100;
+ }
+ }
+ }
+ else
+ {
+ pNearestCity = GC.getMapINLINE().findCity(iX, iY, ((isBarbarian()) ? NO_PLAYER : getID()), ((isBarbarian()) ? NO_TEAM : getTeam()), false);
+ if (pNearestCity != NULL)
+ {
+ int iDistance = plotDistance(iX, iY, pNearestCity->getX_INLINE(), pNearestCity->getY_INLINE());
+ iValue -= std::min(500 * iDistance, (8000 * iDistance) / GC.getMapINLINE().maxPlotDistance());
+ }
+ }
+
+ if (iValue <= 0)
+ {
+ return 1;
+ }
+
+ if (pArea->getNumCities() == 0)
+ {
+ iValue *= 2;
+ }
+ else
+ {
+ iTeamAreaCities = GET_TEAM(getTeam()).countNumCitiesByArea(pArea);
+
+ if (pArea->getNumCities() == iTeamAreaCities)
+ {
+ iValue *= 3;
+ iValue /= 2;
+ }
+ else if (pArea->getNumCities() == (iTeamAreaCities + GET_TEAM(BARBARIAN_TEAM).countNumCitiesByArea(pArea)))
+ {
+ iValue *= 4;
+ iValue /= 3;
+ }
+ else if (iTeamAreaCities > 0)
+ {
+ iValue *= 5;
+ iValue /= 4;
+ }
+ }
+
+ if (!bStartingLoc)
+ {
+ int iFoodSurplus = std::max(0, iSpecialFoodPlus - iSpecialFoodMinus);
+ int iFoodDeficit = std::max(0, iSpecialFoodMinus - iSpecialFoodPlus);
+
+ iValue *= 100 + 20 * std::max(0, std::min(iFoodSurplus, 2 * GC.getFOOD_CONSUMPTION_PER_POPULATION()));
+ iValue /= 100 + 20 * std::max(0, iFoodDeficit);
+ }
+
+ if ((!bStartingLoc) && (getNumCities() > 0))
+ {
+ int iBonusCount = 0;
+ int iUniqueBonusCount = 0;
+ for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
+ {
+ iBonusCount += paiBonusCount[iI];
+ iUniqueBonusCount += (paiBonusCount[iI] > 0) ? 1 : 0;
+ }
+ if (iBonusCount > 4)
+ {
+ iValue *= 5;
+ iValue /= (1 + iBonusCount);
+ }
+ else if (iUniqueBonusCount > 2)
+ {
+ iValue *= 5;
+ iValue /= (3 + iUniqueBonusCount);
+ }
+ }
+
+ if (!bStartingLoc)
+ {
+ int iDeadLockCount = AI_countDeadlockedBonuses(pPlot);
+ if (bAdvancedStart && (iDeadLockCount > 0))
+ {
+ iDeadLockCount += 2;
+ }
+ iValue /= (1 + iDeadLockCount);
+ }
+
+ iValue /= (std::max(0, (iBadTile - (NUM_CITY_PLOTS / 4))) + 3);
+
+ if (bStartingLoc)
+ {
+ iDifferentAreaTile = 0;
+
+ for (iI = 0; iI < NUM_CITY_PLOTS; iI++)
+ {
+ pLoopPlot = plotCity(iX, iY, iI);
+
+ if ((pLoopPlot == NULL) || !(pLoopPlot->isWater() || pLoopPlot->area() == pArea))
+ {
+ iDifferentAreaTile++;
+ }
+ }
+
+ iValue /= (std::max(0, (iDifferentAreaTile - ((NUM_CITY_PLOTS * 2) / 3))) + 2);
+ }
+
+ return std::max(1, iValue);
+}
+
+
+bool CvPlayerAI::AI_isAreaAlone(CvArea* pArea) const
+{
+ return ((pArea->getNumCities() - GET_TEAM(BARBARIAN_TEAM).countNumCitiesByArea(pArea)) == GET_TEAM(getTeam()).countNumCitiesByArea(pArea));
+}
+
+
+bool CvPlayerAI::AI_isCapitalAreaAlone() const
+{
+ CvCity* pCapitalCity;
+
+ pCapitalCity = getCapitalCity();
+
+ if (pCapitalCity != NULL)
+ {
+ return AI_isAreaAlone(pCapitalCity->area());
+ }
+
+ return false;
+}
+
+
+bool CvPlayerAI::AI_isPrimaryArea(CvArea* pArea) const
+{
+ CvCity* pCapitalCity;
+
+ if (pArea->isWater())
+ {
+ return false;
+ }
+
+ if (pArea->getCitiesPerPlayer(getID()) > 2)
+ {
+ return true;
+ }
+
+ pCapitalCity = getCapitalCity();
+
+ if (pCapitalCity != NULL)
+ {
+ if (pCapitalCity->area() == pArea)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+int CvPlayerAI::AI_militaryWeight(CvArea* pArea) const
+{
+ return (pArea->getPopulationPerPlayer(getID()) + pArea->getCitiesPerPlayer(getID()) + 1);
+}
+
+
+int CvPlayerAI::AI_targetCityValue(CvCity* pCity, bool bRandomize, bool bIgnoreAttackers) const
+{
+ PROFILE_FUNC();
+
+ CvCity* pNearestCity;
+ CvPlot* pLoopPlot;
+ int iValue;
+ int iI;
+
+ FAssertMsg(pCity != NULL, "City is not assigned a valid value");
+
+ iValue = 1;
+
+ iValue += ((pCity->getPopulation() * (50 + pCity->calculateCulturePercent(getID()))) / 100);
+
+ if (pCity->getDefenseDamage() > 0)
+ {
+ iValue += ((pCity->getDefenseDamage() / 30) + 1);
+ }
+
+ if (pCity->isCoastal(GC.getMIN_WATER_SIZE_FOR_OCEAN()))
+ {
+ iValue++;
+ }
+
+ if (pCity->hasActiveWorldWonder())
+ {
+ iValue += 1 + pCity->getNumWorldWonders();
+ }
+
+ if (pCity->isHolyCity())
+ {
+ iValue += 2;
+ }
+
+ if (pCity->isEverOwned(getID()))
+ {
+ iValue += 3;
+ }
+ if (!bIgnoreAttackers)
+ {
+ iValue += AI_adjacentPotentialAttackers(pCity->plot());
+ }
+
+ for (iI = 0; iI < NUM_CITY_PLOTS; iI++)
+ {
+ pLoopPlot = plotCity(pCity->getX_INLINE(), pCity->getY_INLINE(), iI);
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->getBonusType(getTeam()) != NO_BONUS)
+ {
+ iValue++;
+ }
+
+ if (pLoopPlot->getOwnerINLINE() == getID())
+ {
+ iValue++;
+ }
+
+ if (pLoopPlot->isAdjacentPlayer(getID(), true))
+ {
+ iValue++;
+ }
+ }
+ }
+
+ pNearestCity = GC.getMapINLINE().findCity(pCity->getX_INLINE(), pCity->getY_INLINE(), getID());
+
+ if (pNearestCity != NULL)
+ {
+ iValue += std::max(1, ((GC.getMapINLINE().maxStepDistance() * 2) - GC.getMapINLINE().calculatePathDistance(pNearestCity->plot(), pCity->plot())));
+ }
+
+ if (bRandomize)
+ {
+ iValue += GC.getGameINLINE().getSorenRandNum(((pCity->getPopulation() / 2) + 1), "AI Target City Value");
+ }
+
+ return iValue;
+}
+
+
+CvCity* CvPlayerAI::AI_findTargetCity(CvArea* pArea) const
+{
+ CvCity* pLoopCity;
+ CvCity* pBestCity;
+ int iValue;
+ int iBestValue;
+ int iLoop;
+ int iI;
+
+ iBestValue = 0;
+ pBestCity = NULL;
+
+ for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isAlive())
+ {
+ if (isPotentialEnemy(getTeam(), GET_PLAYER((PlayerTypes)iI).getTeam()))
+ {
+ for (pLoopCity = GET_PLAYER((PlayerTypes)iI).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER((PlayerTypes)iI).nextCity(&iLoop))
+ {
+ if (pLoopCity->area() == pArea)
+ {
+ iValue = AI_targetCityValue(pLoopCity, true);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ pBestCity = pLoopCity;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return pBestCity;
+}
+
+
+bool CvPlayerAI::AI_isCommercePlot(CvPlot* pPlot) const
+{
+ return (pPlot->getYield(YIELD_FOOD) >= GC.getFOOD_CONSUMPTION_PER_POPULATION());
+}
+
+
+int CvPlayerAI::AI_getPlotDanger(CvPlot* pPlot, int iRange, bool bTestMoves) const
+{
+ PROFILE_FUNC();
+
+ CLLNode* pUnitNode;
+ CvUnit* pLoopUnit;
+ CvPlot* pLoopPlot;
+ int iCount;
+ int iDistance;
+ int iBorderDanger;
+ int iDX, iDY;
+ CvArea *pPlotArea = pPlot->area();
+
+ iCount = 0;
+ iBorderDanger = 0;
+
+ if (iRange == -1)
+ {
+ iRange = DANGER_RANGE;
+ }
+
+ for (iDX = -(iRange); iDX <= iRange; iDX++)
+ {
+ for (iDY = -(iRange); iDY <= iRange; iDY++)
+ {
+ pLoopPlot = plotXY(pPlot->getX_INLINE(), pPlot->getY_INLINE(), iDX, iDY);
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->area() == pPlotArea)
+ {
+ iDistance = stepDistance(pPlot->getX_INLINE(), pPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE());
+ if (atWar(pLoopPlot->getTeam(), getTeam()))
+ {
+ if (iDistance == 1)
+ {
+ iBorderDanger++;
+ }
+ else if ((iDistance == 2) && (pLoopPlot->isRoute()))
+ {
+ iBorderDanger++;
+ }
+ }
+
+
+ pUnitNode = pLoopPlot->headUnitNode();
+
+ while (pUnitNode != NULL)
+ {
+ pLoopUnit = ::getUnit(pUnitNode->m_data);
+ pUnitNode = pLoopPlot->nextUnitNode(pUnitNode);
+
+ if (pLoopUnit->isEnemy(getTeam()))
+ {
+ if (pLoopUnit->canAttack())
+ {
+ if (!(pLoopUnit->isInvisible(getTeam(), false)))
+ {
+ if (pLoopUnit->canMoveOrAttackInto(pPlot))
+ {
+ if (!bTestMoves)
+ {
+ iCount++;
+ }
+ else
+ {
+ int iDangerRange = pLoopUnit->baseMoves();
+ iDangerRange += ((pLoopPlot->isValidRoute(pLoopUnit)) ? 1 : 0);
+ if (iDangerRange >= iDistance)
+ {
+ iCount++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (iBorderDanger > 0)
+ {
+ if (!isHuman() && !pPlot->isCity())
+ {
+ iCount += iBorderDanger;
+ }
+ }
+
+ return iCount;
+}
+
+int CvPlayerAI::AI_getUnitDanger(CvUnit* pUnit, int iRange, bool bTestMoves, bool bAnyDanger) const
+{
+ PROFILE_FUNC();
+
+ CLLNode* pUnitNode;
+ CvUnit* pLoopUnit;
+ CvPlot* pLoopPlot;
+ int iCount;
+ int iDistance;
+ int iBorderDanger;
+ int iDX, iDY;
+
+ CvPlot* pPlot = pUnit->plot();
+ iCount = 0;
+ iBorderDanger = 0;
+
+ if (iRange == -1)
+ {
+ iRange = DANGER_RANGE;
+ }
+
+ for (iDX = -(iRange); iDX <= iRange; iDX++)
+ {
+ for (iDY = -(iRange); iDY <= iRange; iDY++)
+ {
+ pLoopPlot = plotXY(pPlot->getX_INLINE(), pPlot->getY_INLINE(), iDX, iDY);
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->area() == pPlot->area())
+ {
+ iDistance = stepDistance(pPlot->getX_INLINE(), pPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE());
+ if (atWar(pLoopPlot->getTeam(), getTeam()))
+ {
+ if (iDistance == 1)
+ {
+ iBorderDanger++;
+ }
+ else if ((iDistance == 2) && (pLoopPlot->isRoute()))
+ {
+ iBorderDanger++;
+ }
+ }
+
+
+ pUnitNode = pLoopPlot->headUnitNode();
+
+ while (pUnitNode != NULL)
+ {
+ pLoopUnit = ::getUnit(pUnitNode->m_data);
+ pUnitNode = pLoopPlot->nextUnitNode(pUnitNode);
+
+ if (atWar(pLoopUnit->getTeam(), getTeam()))
+ {
+ if (pLoopUnit->canAttack())
+ {
+ if (!(pLoopUnit->isInvisible(getTeam(), false)))
+ {
+ if (pLoopUnit->canMoveOrAttackInto(pPlot))
+ {
+ if (!bTestMoves)
+ {
+ iCount++;
+ }
+ else
+ {
+ int iDangerRange = pLoopUnit->baseMoves();
+ iDangerRange += ((pLoopPlot->isValidRoute(pLoopUnit)) ? 1 : 0);
+ if (iDangerRange >= iDistance)
+ {
+ iCount++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (iBorderDanger > 0)
+ {
+ if (!isHuman() || pUnit->isAutomated())
+ {
+ iCount += iBorderDanger;
+ }
+ }
+
+ return iCount;
+}
+
+int CvPlayerAI::AI_getWaterDanger(CvPlot* pPlot, int iRange, bool bTestMoves) const
+{
+ PROFILE_FUNC();
+
+ CLLNode* pUnitNode;
+ CvUnit* pLoopUnit;
+ CvPlot* pLoopPlot;
+ int iCount;
+ int iDX, iDY;
+
+ iCount = 0;
+
+ if (iRange == -1)
+ {
+ iRange = DANGER_RANGE;
+ }
+
+ CvArea* pWaterArea = pPlot->waterArea();
+
+ for (iDX = -(iRange); iDX <= iRange; iDX++)
+ {
+ for (iDY = -(iRange); iDY <= iRange; iDY++)
+ {
+ pLoopPlot = plotXY(pPlot->getX_INLINE(), pPlot->getY_INLINE(), iDX, iDY);
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->isWater())
+ {
+ if (pPlot->isAdjacentToArea(pLoopPlot->getArea()))
+ {
+ pUnitNode = pLoopPlot->headUnitNode();
+
+ while (pUnitNode != NULL)
+ {
+ pLoopUnit = ::getUnit(pUnitNode->m_data);
+ pUnitNode = pLoopPlot->nextUnitNode(pUnitNode);
+
+ if (pLoopUnit->isEnemy(getTeam()))
+ {
+ if (pLoopUnit->canAttack())
+ {
+ if (!(pLoopUnit->isInvisible(getTeam(), false)))
+ {
+ iCount++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return iCount;
+}
+
+
+bool CvPlayerAI::AI_avoidScience() const
+{
+ if (AI_isDoStrategy(AI_STRATEGY_CULTURE4))
+ {
+ return true;
+ }
+ if (isCurrentResearchRepeat())
+ {
+ return true;
+ }
+
+ if (isNoResearchAvailable())
+ {
+ return true;
+ }
+
+ return false;
+}
+
+
+// XXX
+bool CvPlayerAI::AI_isFinancialTrouble() const
+{
+ //if (getCommercePercent(COMMERCE_GOLD) > 50)
+ {
+ int iNetCommerce = 1 + getCommerceRate(COMMERCE_GOLD) + getCommerceRate(COMMERCE_RESEARCH) + std::max(0, getGoldPerTurn());
+ int iNetExpenses = calculateInflatedCosts() + std::min(0, getGoldPerTurn());
+
+ int iFundedPercent = (100 * (iNetCommerce - iNetExpenses)) / std::max(1, iNetCommerce);
+
+ int iSafePercent = 40;
+ if (AI_avoidScience())
+ {
+ iSafePercent -= 8;
+ }
+
+ if (GET_TEAM(getTeam()).getAnyWarPlanCount(true))
+ {
+ iSafePercent -= 12;
+ }
+
+ if (isCurrentResearchRepeat())
+ {
+ iSafePercent -= 10;
+ }
+
+ if (iFundedPercent < iSafePercent)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+int CvPlayerAI::AI_goldTarget() const
+{
+ int iGold = 0;
+
+ if (GC.getGameINLINE().getElapsedGameTurns() >= 40)
+ {
+ int iMultiplier = 0;
+ iMultiplier += GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getResearchPercent();
+ iMultiplier += GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getTrainPercent();
+ iMultiplier += GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getConstructPercent();
+ iMultiplier /= 3;
+
+ iGold += ((getNumCities() * 3) + (getTotalPopulation() / 3));
+
+ iGold += (GC.getGameINLINE().getElapsedGameTurns() / 2);
+
+ iGold *= iMultiplier;
+ iGold /= 100;
+
+ bool bAnyWar = GET_TEAM(getTeam()).getAnyWarPlanCount(true) > 0;
+ if (bAnyWar)
+ {
+ iGold *= 3;
+ iGold /= 2;
+ }
+
+ if (AI_avoidScience())
+ {
+ iGold *= 10;
+ }
+
+ iGold += (AI_goldToUpgradeAllUnits() / (bAnyWar ? 1 : 2));
+
+ CorporationTypes eActiveCorporation = NO_CORPORATION;
+ for (int iI = 0; iI < GC.getNumCorporationInfos(); iI++)
+ {
+ if (getHasCorporationCount((CorporationTypes)iI) > 0)
+ {
+ eActiveCorporation = (CorporationTypes)iI;
+ break;
+ }
+ }
+ if (eActiveCorporation != NO_CORPORATION)
+ {
+ int iSpreadCost = std::max(0, GC.getCorporationInfo(eActiveCorporation).getSpreadCost() * (100 + calculateInflationRate()));
+ iSpreadCost /= 50;
+ iGold += iSpreadCost;
+ }
+ }
+
+ return iGold + AI_getExtraGoldTarget();
+}
+
+
+TechTypes CvPlayerAI::AI_bestTech(int iMaxPathLength, bool bIgnoreCost, bool bAsync, TechTypes eIgnoreTech, AdvisorTypes eIgnoreAdvisor) const
+{
+ PROFILE("CvPlayerAI::AI_bestTech");
+
+ CvCity* pCapitalCity;
+ ImprovementTypes eImprovement;
+ BuildingTypes eLoopBuilding;
+ RouteTypes eRoute;
+ UnitTypes eLoopUnit;
+ int iPathLength;
+ int iNumBonuses;
+ int iValue;
+ int iTempValue;
+ int iBuildValue;
+ int iBonusValue;
+ int iMilitaryValue;
+ int iI, iJ, iK, iL;
+
+ pCapitalCity = getCapitalCity();
+
+ CvTeam& kTeam = GET_TEAM(getTeam());
+
+ bool bWarPlan = (kTeam.getAnyWarPlanCount(true) > 0);
+ bool bCapitalAlone = (GC.getGameINLINE().getElapsedGameTurns() > 0) ? AI_isCapitalAreaAlone() : false;
+ bool bFinancialTrouble = AI_isFinancialTrouble();
+ bool bAdvancedStart = getAdvancedStartPoints() >= 0;
+
+ int iHasMetCount = kTeam.getHasMetCivCount(true);
+ int iCoastalCities = countNumCoastalCities();
+ int iConnectedForeignCities = countPotentialForeignTradeCitiesConnected();
+
+ int iCityCount = getNumCities();
+ int iTeamCityCount = kTeam.getNumCities();
+
+ int iBestValue = 0;
+ TechTypes eBestTech = NO_TECH;
+
+ int* paiBonusClassRevealed;
+ int* paiBonusClassUnrevealed;
+ int* paiBonusClassHave;
+
+ paiBonusClassRevealed = new int[GC.getNumBonusClassInfos()];
+ paiBonusClassUnrevealed = new int[GC.getNumBonusClassInfos()];
+ paiBonusClassHave = new int[GC.getNumBonusClassInfos()];
+
+ for (iI = 0; iI < GC.getNumBonusClassInfos(); iI++)
+ {
+ paiBonusClassRevealed[iI] = 0;
+ paiBonusClassUnrevealed[iI] = 0;
+ paiBonusClassHave[iI] = 0;
+ }
+
+ for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
+ {
+ TechTypes eRevealTech = (TechTypes)GC.getBonusInfo((BonusTypes)iI).getTechReveal();
+ BonusClassTypes eBonusClass = (BonusClassTypes)GC.getBonusInfo((BonusTypes)iI).getBonusClassType();
+ if (eRevealTech != NO_TECH)
+ {
+ if ((kTeam.isHasTech(eRevealTech)))
+ {
+ paiBonusClassRevealed[eBonusClass]++;
+ }
+ else
+ {
+ paiBonusClassUnrevealed[eBonusClass]++;
+ }
+
+ if (getNumAvailableBonuses((BonusTypes)iI) > 0)
+ {
+ paiBonusClassHave[eBonusClass]++;
+ }
+ else if (countOwnedBonuses((BonusTypes)iI) > 0)
+ {
+ paiBonusClassHave[eBonusClass]++;
+ }
+ }
+ }
+
+ int iPercentOfDomination = 0;
+ int iOurPopPercent = 100 * GET_TEAM(getTeam()).getTotalPopulation() / std::max(1, GC.getGameINLINE().getTotalPopulation());
+
+ for (int iVictory = 0; iVictory < GC.getNumVictoryInfos(); iVictory++)
+ {
+ if (GC.getVictoryInfo((VictoryTypes)iVictory).getPopulationPercentLead() > 0)
+ {
+ iPercentOfDomination = 100 * iOurPopPercent / std::max(1, GC.getGameINLINE().getAdjustedPopulationPercent((VictoryTypes)iVictory));
+ }
+ }
+
+#ifdef DEBUG_TECH_CHOICES
+ CvWString szPlayerName = getName();
+ DEBUGLOG("AI_bestTech:%S\n", szPlayerName.GetCString());
+#endif
+
+ for (iI = 0; iI < GC.getNumTechInfos(); iI++)
+ {
+ if ((eIgnoreTech == NO_TECH) || (iI != eIgnoreTech))
+ {
+ if ((eIgnoreAdvisor == NO_ADVISOR) || (GC.getTechInfo((TechTypes)iI).getAdvisorType() != eIgnoreAdvisor))
+ {
+ if (canEverResearch((TechTypes)iI))
+ {
+ if (!(kTeam.isHasTech((TechTypes)iI)))
+ {
+ if (GC.getTechInfo((TechTypes)iI).getEra() <= (getCurrentEra() + 1))
+ {
+ iPathLength = findPathLength(((TechTypes)iI), false);
+
+ if (iPathLength <= iMaxPathLength)
+ {
+ iValue = 1;
+
+ int iRandomFactor = ((bAsync) ? GC.getASyncRand().get(2000, "AI Research ASYNC") : GC.getGameINLINE().getSorenRandNum(2000, "AI Research"));
+ int iRandomMax = 2000;
+ iValue += iRandomFactor;
+
+ iValue += kTeam.getResearchProgress((TechTypes)iI);
+
+ if (GC.getTechInfo((TechTypes)iI).isExtraWaterSeeFrom())
+ {
+ if (iCoastalCities > 0)
+ {
+ iValue += 100;
+
+ if (bCapitalAlone)
+ {
+ iValue += 400;
+ }
+ }
+ }
+
+ if (GC.getTechInfo((TechTypes)iI).isMapCentering())
+ {
+ iValue += 100;
+ }
+
+ if (GC.getTechInfo((TechTypes)iI).isMapVisible())
+ {
+ iValue += 100;
+
+ if (bCapitalAlone)
+ {
+ iValue += 400;
+ }
+ }
+
+ if (GC.getTechInfo((TechTypes)iI).isMapTrading())
+ {
+ iValue += 100;
+
+ if (bCapitalAlone)
+ {
+ iValue += 400;
+ }
+ }
+
+ if (GC.getTechInfo((TechTypes)iI).isTechTrading() && !GC.getGameINLINE().isOption(GAMEOPTION_NO_TECH_TRADING))
+ {
+ iValue += 500;
+
+ iValue += 500 * iHasMetCount;
+ }
+
+ if (GC.getTechInfo((TechTypes)iI).isGoldTrading())
+ {
+ iValue += 200;
+
+ if (iHasMetCount > 0)
+ {
+ iValue += 400;
+ }
+ }
+
+ if (GC.getTechInfo((TechTypes)iI).isOpenBordersTrading())
+ {
+ if (iHasMetCount > 0)
+ {
+ iValue += 500;
+
+ if (iCoastalCities > 0)
+ {
+ iValue += 400;
+ }
+ }
+ }
+
+ if (GC.getTechInfo((TechTypes)iI).isDefensivePactTrading())
+ {
+ iValue += 400;
+ }
+
+ if (GC.getTechInfo((TechTypes)iI).isPermanentAllianceTrading())
+ {
+ iValue += 200;
+ }
+
+ if (GC.getTechInfo((TechTypes)iI).isVassalStateTrading())
+ {
+ iValue += 200;
+ }
+
+ if (GC.getTechInfo((TechTypes)iI).isBridgeBuilding())
+ {
+ iValue += 200;
+ }
+
+ if (GC.getTechInfo((TechTypes)iI).isIrrigation())
+ {
+ iValue += 400;
+ }
+
+ if (GC.getTechInfo((TechTypes)iI).isIgnoreIrrigation())
+ {
+ iValue += 500;
+ }
+
+ if (GC.getTechInfo((TechTypes)iI).isWaterWork())
+ {
+ iValue += (600 * iCoastalCities);
+ }
+
+ iValue += (GC.getTechInfo((TechTypes)iI).getFeatureProductionModifier() * 2);
+ iValue += (GC.getTechInfo((TechTypes)iI).getWorkerSpeedModifier() * 4);
+ iValue += (GC.getTechInfo((TechTypes)iI).getTradeRoutes() * (std::max((getNumCities() + 2), iConnectedForeignCities) + 1) * ((bFinancialTrouble) ? 200 : 100));
+
+ if (iPercentOfDomination < 90)
+ {
+ iValue += (GC.getTechInfo((TechTypes)iI).getHealth() * 200);
+ }
+ else
+ {
+ iValue += (GC.getTechInfo((TechTypes)iI).getHealth() * 350);
+ }
+
+ for (iJ = 0; iJ < GC.getNumRouteInfos(); iJ++)
+ {
+ iValue += -(GC.getRouteInfo((RouteTypes)iJ).getTechMovementChange(iI) * 100);
+ }
+
+ for (iJ = 0; iJ < NUM_DOMAIN_TYPES; iJ++)
+ {
+ iValue += (GC.getTechInfo((TechTypes)iI).getDomainExtraMoves(iJ) * 200);
+ }
+
+ for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
+ {
+ if (GC.getTechInfo((TechTypes)iI).isCommerceFlexible(iJ))
+ {
+ iValue += 100;
+ if ((iJ == COMMERCE_CULTURE) && (AI_isDoStrategy(AI_STRATEGY_CULTURE2)))
+ {
+ iValue += 1000;
+ }
+ }
+ }
+
+ for (iJ = 0; iJ < GC.getNumTerrainInfos(); iJ++)
+ {
+ if (GC.getTechInfo((TechTypes)iI).isTerrainTrade(iJ))
+ {
+ if (GC.getTerrainInfo((TerrainTypes)iJ).isWater())
+ {
+ if (pCapitalCity != NULL)
+ {
+ iValue += (countPotentialForeignTradeCities(pCapitalCity->area()) * 100);
+ }
+
+ if (iCoastalCities > 0)
+ {
+ iValue += ((bCapitalAlone) ? 950 : 350);
+ }
+
+ iValue += 50;
+ }
+ else
+ {
+ iValue += 1000;
+ }
+ }
+ }
+
+ if (GC.getTechInfo((TechTypes)iI).isRiverTrade())
+ {
+ iValue += 1000;
+ }
+
+ for (iJ = 0; iJ < GC.getNumImprovementInfos(); iJ++)
+ {
+ for (iK = 0; iK < NUM_YIELD_TYPES; iK++)
+ {
+ iTempValue = 0;
+
+ iTempValue += (GC.getImprovementInfo((ImprovementTypes)iJ).getTechYieldChanges(iI, iK) * getImprovementCount((ImprovementTypes)iJ) * 50);
+
+ iTempValue *= AI_yieldWeight((YieldTypes)iK);
+ iTempValue /= 100;
+
+ iValue += iTempValue;
+ }
+ }
+
+ iBuildValue = 0;
+ for (iJ = 0; iJ < GC.getNumBuildInfos(); iJ++)
+ {
+ if (GC.getBuildInfo((BuildTypes)iJ).getTechPrereq() == iI)
+ {
+ eImprovement = (ImprovementTypes)(GC.getBuildInfo((BuildTypes)iJ).getImprovement());
+ if (eImprovement != NO_IMPROVEMENT)
+ {
+ eImprovement = finalImprovementUpgrade(eImprovement);
+ }
+ else
+ {
+ // only increment build value if it is not an improvement, otherwise handle it there
+ iBuildValue += 200;
+ }
+
+ if (eImprovement != NO_IMPROVEMENT)
+ {
+ CvImprovementInfo& kImprovement = GC.getImprovementInfo(eImprovement);
+
+ int iImprovementValue = 300;
+
+ iImprovementValue += ((kImprovement.isActsAsCity()) ? 100 : 0);
+ iImprovementValue += ((kImprovement.isHillsMakesValid()) ? 100 : 0);
+ iImprovementValue += ((kImprovement.isFreshWaterMakesValid()) ? 200 : 0);
+ iImprovementValue += ((kImprovement.isRiverSideMakesValid()) ? 100 : 0);
+ iImprovementValue += ((kImprovement.isCarriesIrrigation()) ? 300 : 0);
+
+ for (iK = 0; iK < GC.getNumTerrainInfos(); iK++)
+ {
+ iImprovementValue += (kImprovement.getTerrainMakesValid(iK) ? 50 : 0);
+ }
+
+ for (iK = 0; iK < GC.getNumFeatureInfos(); iK++)
+ {
+ iImprovementValue += (kImprovement.getFeatureMakesValid(iK) ? 50 : 0);
+ }
+
+ for (iK = 0; iK < NUM_YIELD_TYPES; iK++)
+ {
+ iTempValue = 0;
+
+ iTempValue += (kImprovement.getYieldChange(iK) * 200);
+ iTempValue += (kImprovement.getRiverSideYieldChange(iK) * 100);
+ iTempValue += (kImprovement.getHillsYieldChange(iK) * 100);
+ iTempValue += (kImprovement.getIrrigatedYieldChange(iK) * 150);
+
+ // land food yield is more valueble
+ if (iK == YIELD_FOOD && !kImprovement.isWater())
+ {
+ iTempValue *= 3;
+ iTempValue /= 2;
+ }
+
+ if (bFinancialTrouble && iK == YIELD_COMMERCE)
+ {
+ iTempValue *= 2;
+ }
+
+ iTempValue *= AI_yieldWeight((YieldTypes)iK);
+ iTempValue /= 100;
+
+ iImprovementValue += iTempValue;
+ }
+
+ for (iK = 0; iK < GC.getNumBonusInfos(); iK++)
+ {
+ iBonusValue = 0;
+
+ iBonusValue += ((kImprovement.isImprovementBonusMakesValid(iK)) ? 450 : 0);
+ iBonusValue += ((kImprovement.isImprovementBonusTrade(iK)) ? (45 * AI_bonusVal((BonusTypes) iK)) : 0);
+
+ if (iBonusValue > 0)
+ {
+ for (iL = 0; iL < NUM_YIELD_TYPES; iL++)
+ {
+ iTempValue = 0;
+
+ iTempValue += (kImprovement.getImprovementBonusYield(iK, iL) * 300);
+ iTempValue += (kImprovement.getIrrigatedYieldChange(iL) * 200);
+
+ // food bonuses are more valueble
+ if (iL == YIELD_FOOD)
+ {
+ iTempValue *= 2;
+ }
+ // otherwise, devalue the bonus slightly
+ else if (iL == YIELD_COMMERCE && bFinancialTrouble)
+ {
+ iTempValue *= 4;
+ iTempValue /= 3;
+ }
+ else
+ {
+ iTempValue *= 3;
+ iTempValue /= 4;
+ }
+
+ if (bAdvancedStart && getCurrentEra() < 2)
+ {
+ iValue *= (iL == YIELD_FOOD) ? 3 : 2;
+ }
+
+ iTempValue *= AI_yieldWeight((YieldTypes)iL);
+ iTempValue /= 100;
+
+ iBonusValue += iTempValue;
+ }
+
+ iNumBonuses = countOwnedBonuses((BonusTypes)iK);
+
+ if (iNumBonuses > 0)
+ {
+ iBonusValue *= (iNumBonuses + 2);
+ iBonusValue /= kImprovement.isWater() ? 4 : 3; // water resources are worth less
+
+ iImprovementValue += iBonusValue;
+ }
+ }
+ }
+
+ // if water improvement, weight by coastal cities (weight the whole build)
+ if (kImprovement.isWater())
+ {
+ iImprovementValue *= iCoastalCities;
+ iImprovementValue /= std::max(1, iCityCount/2);
+ }
+
+ iBuildValue += iImprovementValue;
+ }
+
+ eRoute = ((RouteTypes)(GC.getBuildInfo((BuildTypes)iJ).getRoute()));
+
+ if (eRoute != NO_ROUTE)
+ {
+ iBuildValue += ((getBestRoute() == NO_ROUTE) ? 700 : 200) * (getNumCities() + (bAdvancedStart ? 4 : 0));
+
+ for (iK = 0; iK < NUM_YIELD_TYPES; iK++)
+ {
+ iTempValue = 0;
+
+ iTempValue += (GC.getRouteInfo(eRoute).getYieldChange(iK) * 100);
+
+ for (iL = 0; iL < GC.getNumImprovementInfos(); iL++)
+ {
+ iTempValue += (GC.getImprovementInfo((ImprovementTypes)iL).getRouteYieldChanges(eRoute, iK) * 50);
+ }
+
+ iTempValue *= AI_yieldWeight((YieldTypes)iK);
+ iTempValue /= 100;
+
+ iBuildValue += iTempValue;
+ }
+ }
+ }
+ }
+
+ //the way feature-remove is done in XML is pretty weird
+ //I believe this code needs to be outside the general BuildTypes loop
+ //to ensure the feature-remove is only counted once rather than once per build
+ //which could be a lot since nearly every build clears jungle...
+
+ for (iJ = 0; iJ < GC.getNumFeatureInfos(); iJ++)
+ {
+ bool bIsFeatureRemove = false;
+ for (iK = 0; iK < GC.getNumBuildInfos(); iK++)
+ {
+ if (GC.getBuildInfo((BuildTypes)iK).getFeatureTech(iJ) == iI)
+ {
+ bIsFeatureRemove = true;
+ break;
+ }
+ }
+
+ if (bIsFeatureRemove)
+ {
+ iBuildValue += 100;
+
+ if ((GC.getFeatureInfo(FeatureTypes(iJ)).getHealthPercent() < 0) ||
+ ((GC.getFeatureInfo(FeatureTypes(iJ)).getYieldChange(YIELD_FOOD) + GC.getFeatureInfo(FeatureTypes(iJ)).getYieldChange(YIELD_PRODUCTION) + GC.getFeatureInfo(FeatureTypes(iJ)).getYieldChange(YIELD_COMMERCE)) < 0))
+ {
+ iBuildValue += 25 * countCityFeatures((FeatureTypes)iJ);
+ }
+ }
+ }
+
+ /*if (AI_totalUnitAIs(UNITAI_WORKER) == 0)
+ {
+ iBuildValue /= 2;
+ }*/
+
+ iValue += iBuildValue;
+
+ // does tech reveal bonus resources
+ for (iJ = 0; iJ < GC.getNumBonusInfos(); iJ++)
+ {
+ if (GC.getBonusInfo((BonusTypes)iJ).getTechReveal() == iI)
+ {
+ int iRevealValue = 150;
+ iRevealValue += (AI_bonusVal((BonusTypes)iJ) * 50);
+
+ BonusClassTypes eBonusClass = (BonusClassTypes)GC.getBonusInfo((BonusTypes)iJ).getBonusClassType();
+ int iBonusClassTotal = (paiBonusClassRevealed[eBonusClass] + paiBonusClassUnrevealed[eBonusClass]);
+
+ //iMultiplier is basically a desperation value
+ //it gets larger as the AI runs out of options
+ //Copper after failing to get horses is +66%
+ //Iron after failing to get horse or copper is +200%
+ //but with either copper or horse, Iron is only +25%
+ int iMultiplier = 0;
+ if (iBonusClassTotal > 0)
+ {
+ iMultiplier = (paiBonusClassRevealed[eBonusClass] - paiBonusClassHave[eBonusClass]);
+ iMultiplier *= 100;
+ iMultiplier /= iBonusClassTotal;
+
+ iMultiplier *= (paiBonusClassRevealed[eBonusClass] + 1);
+ iMultiplier /= ((paiBonusClassHave[eBonusClass] * iBonusClassTotal) + 1);
+ }
+
+ iMultiplier *= std::min(3, getNumCities());
+ iMultiplier /= 3;
+
+ iRevealValue *= 100 + iMultiplier;
+ iRevealValue /= 100;
+
+
+ iValue += iRevealValue;
+
+ }
+ }
+
+ bool bEnablesUnitWonder = false;
+ for (iJ = 0; iJ < GC.getNumUnitClassInfos(); iJ++)
+ {
+ eLoopUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iJ)));
+
+ if (eLoopUnit != NO_UNIT)
+ {
+ if (isTechRequiredForUnit(((TechTypes)iI), eLoopUnit))
+ {
+ CvUnitInfo& kLoopUnit = GC.getUnitInfo(eLoopUnit);
+ iValue += 200;
+ int iUnitValue = 0;
+ int iNavalValue = 0;
+
+ if ((GC.getUnitClassInfo((UnitClassTypes)iJ).getDefaultUnitIndex()) != (GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iJ)))
+ {
+ //UU
+ iUnitValue += 600;
+ }
+
+ if (kLoopUnit.getPrereqAndTech() == iI)
+ {
+ iMilitaryValue = 0;
+
+ switch (kLoopUnit.getDefaultUnitAIType())
+ {
+ case UNITAI_UNKNOWN:
+ case UNITAI_ANIMAL:
+ break;
+
+ case UNITAI_SETTLE:
+ iUnitValue += 1200;
+ break;
+
+ case UNITAI_WORKER:
+ iUnitValue += 800;
+ break;
+
+ case UNITAI_ATTACK:
+ iMilitaryValue += ((bWarPlan) ? 600 : 300);
+ iMilitaryValue += (AI_isDoStrategy(AI_STRATEGY_DAGGER ) ? 800 : 0);
+ iUnitValue += 100;
+ break;
+
+ case UNITAI_ATTACK_CITY:
+ iMilitaryValue += ((bWarPlan) ? 800 : 400);
+ iMilitaryValue += (AI_isDoStrategy(AI_STRATEGY_DAGGER ) ? 800 : 0);
+ if (kLoopUnit.getBombardRate() > 0)
+ {
+ iMilitaryValue += 200;
+
+ if (AI_calculateTotalBombard(DOMAIN_LAND) == 0)
+ {
+ iMilitaryValue += 800;
+ if (AI_isDoStrategy(AI_STRATEGY_DAGGER))
+ {
+ iMilitaryValue += 1000;
+ }
+ }
+ }
+ iUnitValue += 100;
+ break;
+
+ case UNITAI_COLLATERAL:
+ iMilitaryValue += ((bWarPlan) ? 600 : 300);
+ iMilitaryValue += (AI_isDoStrategy(AI_STRATEGY_DAGGER ) ? 500 : 0);
+ break;
+
+ case UNITAI_PILLAGE:
+ iMilitaryValue += ((bWarPlan) ? 200 : 100);
+ break;
+
+ case UNITAI_RESERVE:
+ iMilitaryValue += ((bWarPlan) ? 200 : 100);
+ break;
+
+ case UNITAI_COUNTER:
+ iMilitaryValue += ((bWarPlan) ? 600 : 300);
+ iMilitaryValue += (AI_isDoStrategy(AI_STRATEGY_DAGGER ) ? 600 : 0);
+ break;
+
+ case UNITAI_PARADROP:
+ iMilitaryValue += ((bWarPlan) ? 600 : 300);
+ break;
+
+ case UNITAI_CITY_DEFENSE:
+ iMilitaryValue += ((bWarPlan) ? 800 : 400);
+ iMilitaryValue += ((!bCapitalAlone) ? 400 : 200);
+ iUnitValue += ((iHasMetCount > 0) ? 800 : 200);
+ break;
+
+ case UNITAI_CITY_COUNTER:
+ iMilitaryValue += ((bWarPlan) ? 800 : 400);
+ break;
+
+ case UNITAI_CITY_SPECIAL:
+ iMilitaryValue += ((bWarPlan) ? 800 : 400);
+ break;
+
+ case UNITAI_EXPLORE:
+ iUnitValue += ((bCapitalAlone) ? 100 : 200);
+ break;
+
+ case UNITAI_MISSIONARY:
+ iUnitValue += ((getStateReligion() != NO_RELIGION) ? 600 : 300);
+ break;
+
+ case UNITAI_PROPHET:
+ case UNITAI_ARTIST:
+ case UNITAI_SCIENTIST:
+ case UNITAI_GENERAL:
+ case UNITAI_MERCHANT:
+ case UNITAI_ENGINEER:
+ break;
+
+ case UNITAI_SPY:
+ iMilitaryValue += ((bWarPlan) ? 100 : 50);
+ break;
+
+ case UNITAI_ICBM:
+ iMilitaryValue += ((bWarPlan) ? 200 : 100);
+ break;
+
+ case UNITAI_WORKER_SEA:
+ if (iCoastalCities > 0)
+ {
+ // note, workboat improvements are already counted in the improvement section above
+ }
+ break;
+
+ case UNITAI_ATTACK_SEA:
+ if (iCoastalCities > 0)
+ {
+ iMilitaryValue += ((bWarPlan) ? 200 : 100);
+ }
+ iNavalValue += 100;
+ break;
+
+ case UNITAI_RESERVE_SEA:
+ if (iCoastalCities > 0)
+ {
+ iMilitaryValue += ((bWarPlan) ? 100 : 50);
+ }
+ iNavalValue += 100;
+ break;
+
+ case UNITAI_ESCORT_SEA:
+ if (iCoastalCities > 0)
+ {
+ iMilitaryValue += ((bWarPlan) ? 100 : 50);
+ }
+ iNavalValue += 100;
+ break;
+
+ case UNITAI_EXPLORE_SEA:
+ if (iCoastalCities > 0)
+ {
+ iUnitValue += ((bCapitalAlone) ? 1800 : 600);
+ }
+ break;
+
+ case UNITAI_ASSAULT_SEA:
+ if (iCoastalCities > 0)
+ {
+ iMilitaryValue += ((bWarPlan || bCapitalAlone) ? 400 : 200);
+ }
+ iNavalValue += 200;
+ break;
+
+ case UNITAI_SETTLER_SEA:
+ if (iCoastalCities > 0)
+ {
+ iUnitValue += ((bWarPlan || bCapitalAlone) ? 100 : 200);
+ }
+ iNavalValue += 200;
+ break;
+
+ case UNITAI_MISSIONARY_SEA:
+ if (iCoastalCities > 0)
+ {
+ iUnitValue += 100;
+ }
+ break;
+
+ case UNITAI_SPY_SEA:
+ if (iCoastalCities > 0)
+ {
+ iMilitaryValue += 100;
+ }
+ break;
+
+ case UNITAI_CARRIER_SEA:
+ if (iCoastalCities > 0)
+ {
+ iMilitaryValue += ((bWarPlan) ? 100 : 50);
+ }
+ break;
+
+ case UNITAI_MISSILE_CARRIER_SEA:
+ if (iCoastalCities > 0)
+ {
+ iMilitaryValue += ((bWarPlan) ? 100 : 50);
+ }
+ break;
+
+ case UNITAI_PIRATE_SEA:
+ if (iCoastalCities > 0)
+ {
+ iMilitaryValue += 100;
+ }
+ iNavalValue += 100;
+ break;
+
+ case UNITAI_ATTACK_AIR:
+ iMilitaryValue += ((bWarPlan) ? 1200 : 800);
+ break;
+
+ case UNITAI_DEFENSE_AIR:
+ iMilitaryValue += ((bWarPlan) ? 1200 : 800);
+ break;
+
+ case UNITAI_CARRIER_AIR:
+ if (iCoastalCities > 0)
+ {
+ iMilitaryValue += ((bWarPlan) ? 200 : 100);
+ }
+ iNavalValue += 400;
+ break;
+
+ case UNITAI_MISSILE_AIR:
+ iMilitaryValue += ((bWarPlan) ? 200 : 100);
+ break;
+
+ default:
+ FAssert(false);
+ break;
+ }
+
+ if (iHasMetCount == 0)
+ {
+ iMilitaryValue /= 2;
+ }
+
+ if (bCapitalAlone)
+ {
+ iMilitaryValue *= 2;
+ iMilitaryValue /= 3;
+ }
+
+ if (kLoopUnit.getUnitAIType(UNITAI_ASSAULT_SEA))
+ {
+ int iAssaultValue = 0;
+ UnitTypes eExistingUnit;
+ if (AI_bestAreaUnitAIValue(UNITAI_ASSAULT_SEA, NULL, &eExistingUnit) == 0)
+ {
+ iAssaultValue += 1000;
+ }
+ else
+ {
+ iAssaultValue += 100 * std::max(0, AI_unitImpassableCount(eLoopUnit) - AI_unitImpassableCount(eExistingUnit));
+ if (iAssaultValue > 0)
+ {
+ iAssaultValue += 200;
+ }
+ int iNewCapacity = kLoopUnit.getMoves() * kLoopUnit.getCargoSpace();
+ int iOldCapacity = GC.getUnitInfo(eExistingUnit).getMoves() * GC.getUnitInfo(eExistingUnit).getCargoSpace();
+ iAssaultValue += (800 * (iNewCapacity - iOldCapacity)) / iOldCapacity;
+ }
+
+ if (iAssaultValue > 0)
+ {
+ int iLoop;
+ CvArea* pLoopArea;
+ bool bIsAnyAssault = false;
+ for(pLoopArea = GC.getMapINLINE().firstArea(&iLoop); pLoopArea != NULL; pLoopArea = GC.getMapINLINE().nextArea(&iLoop))
+ {
+ if (AI_isPrimaryArea(pLoopArea))
+ {
+ if (pLoopArea->getAreaAIType(getTeam()) == AREAAI_ASSAULT)
+ {
+ bIsAnyAssault = true;
+ break;
+ }
+ }
+ }
+ if (bIsAnyAssault)
+ {
+ iNavalValue += iAssaultValue;
+ }
+ else
+ {
+ iNavalValue += iAssaultValue / 6;
+ }
+ }
+ }
+
+ if (iNavalValue > 0)
+ {
+ if (getCapitalCity() != NULL)
+ {
+ iNavalValue *= 2 * (getNumCities() - getCapitalCity()->area()->getCitiesPerPlayer(getID()));
+ iNavalValue /= getNumCities();
+
+ iUnitValue += iNavalValue;
+ }
+ }
+
+ iUnitValue += iMilitaryValue;
+
+ if (AI_totalUnitAIs((UnitAITypes)(kLoopUnit.getDefaultUnitAIType())) == 0)
+ {
+ // do not give bonus to seagoing units if they are worthless
+ if (iUnitValue > 0)
+ {
+ iUnitValue *= 2;
+ }
+
+ if (kLoopUnit.getDefaultUnitAIType() == UNITAI_EXPLORE)
+ {
+ if (pCapitalCity != NULL)
+ {
+ iUnitValue += (AI_neededExplorers(pCapitalCity->area()) * 400);
+ }
+ }
+
+ if (kLoopUnit.getDefaultUnitAIType() == UNITAI_EXPLORE_SEA)
+ {
+ iUnitValue += 400;
+ iUnitValue += ((GC.getGameINLINE().countCivTeamsAlive() - iHasMetCount) * 200);
+ }
+ }
+ //Early Expansion by sea
+ if (kLoopUnit.getUnitAIType(UNITAI_SETTLER_SEA))
+ {
+ if (AI_totalUnitAIs(UNITAI_SETTLER_SEA) == 0)
+ {
+ if (getCapitalCity() != NULL)
+ {
+ CvArea* pWaterArea = getCapitalCity()->waterArea();
+ if (pWaterArea != NULL)
+ {
+ int iBestAreaValue = 0;
+ int iBestOtherValue = 0;
+ AI_getNumAreaCitySites(getCapitalCity()->getArea(), iBestAreaValue);
+ AI_getNumAdjacentAreaCitySites(pWaterArea->getID(), getCapitalCity()->getArea(), iBestOtherValue);
+
+ if (iBestAreaValue == 0)
+ {
+ iUnitValue += 2000;
+ }
+ else if (iBestAreaValue < iBestOtherValue)
+ {
+ iUnitValue += 1000;
+ }
+ else if (iBestOtherValue > 0)
+ {
+ iUnitValue += 500;
+ }
+ }
+ }
+ }
+ }
+
+ if (iPathLength <= 1)
+ {
+ if (getTotalPopulation() > 5)
+ {
+ if (isWorldUnitClass((UnitClassTypes)iJ))
+ {
+ if (!(GC.getGameINLINE().isUnitClassMaxedOut((UnitClassTypes)iJ)))
+ {
+ bEnablesUnitWonder = true;
+ }
+ }
+ }
+ }
+
+ iValue += iUnitValue;
+ }
+ }
+ }
+ }
+ if (bEnablesUnitWonder)
+ {
+ int iWonderRandom = ((bAsync) ? GC.getASyncRand().get(400, "AI Research Wonder Unit ASYNC") : GC.getGameINLINE().getSorenRandNum(400, "AI Research Wonder Unit"));
+ iValue += iWonderRandom + (bCapitalAlone ? 200 : 0);
+
+ iRandomMax += 400;
+ iRandomFactor += iWonderRandom;
+ }
+
+ int iBestLandBuildingValue = 0;
+ bool bEnablesWonder = false;
+ int iExistingCultureBuildingCount = 0;
+ bool bIsCultureBuilding = false;
+ for (iJ = 0; iJ < GC.getNumBuildingClassInfos(); iJ++)
+ {
+ eLoopBuilding = ((BuildingTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iJ)));
+
+ if (eLoopBuilding != NO_BUILDING)
+ {
+ CvBuildingInfo& kLoopBuilding = GC.getBuildingInfo(eLoopBuilding);
+ if (isTechRequiredForBuilding(((TechTypes)iI), eLoopBuilding))
+ {
+ int iBuildingValue = 0;
+
+ if (kLoopBuilding.getSpecialBuildingType() != NO_BUILDING)
+ {
+ iBuildingValue += ((bCapitalAlone) ? 100 : 25);
+ }
+ else
+ {
+ iBuildingValue += ((bCapitalAlone) ? 200 : 50);
+ }
+
+ //the granary effect is SO powerful it deserves special code
+ if (kLoopBuilding.getFoodKept() > 0)
+ {
+ iBuildingValue += (15 * kLoopBuilding.getFoodKept());
+ }
+
+ if (kLoopBuilding.getMaintenanceModifier() < 0)
+ {
+ int iLoop;
+ int iCount = 0;
+ CvCity* pLoopCity;
+ iTempValue = 0;
+ for (pLoopCity = firstCity(&iLoop, true); pLoopCity != NULL; pLoopCity = nextCity(&iLoop, true))
+ {
+ iTempValue += pLoopCity->getMaintenanceTimes100();
+ iCount++;
+ if (iCount > 4)
+ {
+ break;
+ }
+ }
+ iTempValue /= std::max(1, iCount);
+ iTempValue *= -kLoopBuilding.getMaintenanceModifier();
+ iTempValue /= 10 * 100;
+ }
+
+ iBuildingValue += 100;
+
+ if ((GC.getBuildingClassInfo((BuildingClassTypes)iJ).getDefaultBuildingIndex()) != (GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iJ)))
+ {
+ //UB
+ iBuildingValue += 600;
+ }
+
+ if (kLoopBuilding.getCommerceChange(COMMERCE_CULTURE) > 0)
+ {
+ bIsCultureBuilding = true;
+ }
+
+ if (AI_isDoStrategy(AI_STRATEGY_CULTURE2))
+ {
+ int iMultiplier = (isLimitedWonderClass((BuildingClassTypes)iJ) ? 1 : 3);
+ iBuildingValue += (150 * kLoopBuilding.getCommerceChange(COMMERCE_CULTURE)) * iMultiplier;
+ iBuildingValue += kLoopBuilding.getCommerceModifier(COMMERCE_CULTURE) * 4 * iMultiplier ;
+ }
+
+ if (bFinancialTrouble)
+ {
+ iBuildingValue += kLoopBuilding.getMaintenanceModifier() * 15;
+ iBuildingValue += kLoopBuilding.getYieldModifier(YIELD_COMMERCE) * 8;
+ iBuildingValue += kLoopBuilding.getCommerceModifier(COMMERCE_GOLD) * 15;
+ }
+
+ // if this is a religious building, its not as useful
+ ReligionTypes eReligion = (ReligionTypes) kLoopBuilding.getReligionType();
+ if (eReligion != NO_RELIGION)
+ {
+
+ // reduce by a factor based on how many cities we have with that relgion
+ if (iTeamCityCount > 0)
+ {
+ int iCitiesWithReligion = kTeam.getHasReligionCount(eReligion);
+
+ iBuildingValue *= (4 + iCitiesWithReligion);
+ iBuildingValue /= (4 + iTeamCityCount);
+ }
+
+ // if this building requires a religion, then only count it as 1/7th as much
+ // or in other words, only count things like temples once, not 7 times
+ // doing it this way in case some mods give buildings to only one religion
+ iBuildingValue /= std::max(1, GC.getNumReligionInfos());
+ }
+
+ // if we're close to pop domination, we love medicine!
+ // don't adjust for negative modifiers to prevent ignoring assembly line, etc.
+ if (iPercentOfDomination >= 90 && kLoopBuilding.getHealth() > 0)
+ {
+ iBuildingValue += kLoopBuilding.getHealth() * 150;
+ }
+
+ if (kLoopBuilding.getPrereqAndTech() == iI)
+ {
+ if (iPathLength <= 1)
+ {
+ if (getTotalPopulation() > 5)
+ {
+ if (isWorldWonderClass((BuildingClassTypes)iJ))
+ {
+ if (!(GC.getGameINLINE().isBuildingClassMaxedOut((BuildingClassTypes)iJ)))
+ {
+ bEnablesWonder = true;
+
+ if (AI_isDoStrategy(AI_STRATEGY_CULTURE1))
+ {
+ iValue += 400;
+ }
+
+ if (bCapitalAlone)
+ {
+ iBuildingValue += 400;
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ if (iBuildingValue > iBestLandBuildingValue)
+ {
+ iBestLandBuildingValue = iBuildingValue;
+ }
+
+ // if water building, weight by coastal cities
+ if (kLoopBuilding.isWater())
+ {
+ iBuildingValue *= iCoastalCities;
+ iBuildingValue /= std::max(1, iCityCount/2);
+ }
+ // if land building, is it the best?
+ else if (iBuildingValue > iBestLandBuildingValue)
+ {
+ iBestLandBuildingValue = iBuildingValue;
+ }
+
+ iValue += iBuildingValue;
+ }
+ else
+ {
+ if (canConstruct(eLoopBuilding))
+ {
+ if (!isLimitedWonderClass((BuildingClassTypes)iJ))
+ {
+ if (kLoopBuilding.getCommerceChange(COMMERCE_CULTURE) > 0)
+ {
+ iExistingCultureBuildingCount++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (bIsCultureBuilding && iExistingCultureBuildingCount < 2)
+ {
+ if (getFreeCityCommerce(COMMERCE_CULTURE) == 0)
+ {
+ if (getNumCities() > 1)
+ {
+ iValue += 150 * std::max(1, (3 - 2 * iExistingCultureBuildingCount)) * (getNumCities() - 1);
+ }
+ }
+ }
+ // if tech gives at least one building (so we can count each individual building less)
+ if (iBestLandBuildingValue > 0)
+ {
+ iValue += iBestLandBuildingValue;
+ }
+
+ // if it gives at least one wonder
+ if (bEnablesWonder)
+ {
+ int iWonderRandom = ((bAsync) ? GC.getASyncRand().get(800, "AI Research Wonder Building ASYNC") : GC.getGameINLINE().getSorenRandNum(800, "AI Research Wonder Building"));
+ iValue += (500 + iWonderRandom) / (bAdvancedStart ? 5 : 1);
+
+ iRandomMax += 800;
+ iRandomFactor += iWonderRandom;
+ }
+
+ bool bEnablesProjectWonder = false;
+ for (iJ = 0; iJ < GC.getNumProjectInfos(); iJ++)
+ {
+ if (GC.getProjectInfo((ProjectTypes)iJ).getTechPrereq() == iI)
+ {
+ iValue += 1000;
+
+ if (iPathLength <= 1)
+ {
+ if (getTotalPopulation() > 5)
+ {
+ if (isWorldProject((ProjectTypes)iJ))
+ {
+ if (!(GC.getGameINLINE().isProjectMaxedOut((ProjectTypes)iJ)))
+ {
+ bEnablesProjectWonder = true;
+
+ if (bCapitalAlone)
+ {
+ iValue += 100;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (bEnablesProjectWonder)
+ {
+ int iWonderRandom = ((bAsync) ? GC.getASyncRand().get(200, "AI Research Wonder Project ASYNC") : GC.getGameINLINE().getSorenRandNum(200, "AI Research Wonder Project"));
+ iValue += iWonderRandom;
+
+ iRandomMax += 200;
+ iRandomFactor += iWonderRandom;
+ }
+
+ bool bIsGoodProcess = false;
+
+ for (iJ = 0; iJ < GC.getNumProcessInfos(); iJ++)
+ {
+ if (GC.getProcessInfo((ProcessTypes)iJ).getTechPrereq() == iI)
+ {
+ iValue += 100;
+
+ for (iK = 0; iK < NUM_COMMERCE_TYPES; iK++)
+ {
+ iTempValue = (GC.getProcessInfo((ProcessTypes)iJ).getProductionToCommerceModifier(iK) * 4);
+
+ iTempValue *= AI_commerceWeight((CommerceTypes)iK);
+ iTempValue /= 100;
+
+ if (iK == COMMERCE_GOLD || iK == COMMERCE_RESEARCH)
+ {
+ bIsGoodProcess = true;
+ }
+ else if ((iK == COMMERCE_CULTURE) && AI_isDoStrategy(AI_STRATEGY_CULTURE1))
+ {
+ iTempValue *= 3;
+ }
+
+ iValue += iTempValue;
+ }
+ }
+ }
+
+ if (bIsGoodProcess && bFinancialTrouble)
+ {
+ bool bHaveGoodProcess = false;
+ for (iJ = 0; iJ < GC.getNumProcessInfos(); iJ++)
+ {
+ if (kTeam.isHasTech((TechTypes)GC.getProcessInfo((ProcessTypes)iJ).getTechPrereq()))
+ {
+ bHaveGoodProcess = (GC.getProcessInfo((ProcessTypes)iJ).getProductionToCommerceModifier(COMMERCE_GOLD) + GC.getProcessInfo((ProcessTypes)iJ).getProductionToCommerceModifier(COMMERCE_RESEARCH)) > 0;
+ if (bHaveGoodProcess)
+ {
+ break;
+ }
+ }
+ }
+ if (!bHaveGoodProcess)
+ {
+ iValue += 1500;
+ }
+ }
+
+ for (iJ = 0; iJ < GC.getNumCivicInfos(); iJ++)
+ {
+ if (GC.getCivicInfo((CivicTypes)iJ).getTechPrereq() == iI)
+ {
+ iValue += 200;
+
+ CivicTypes eCivic = getCivics((CivicOptionTypes)(GC.getCivicInfo((CivicTypes)iJ).getCivicOptionType()));
+ if (NO_CIVIC != eCivic)
+ {
+ int iCurrentCivicValue = AI_civicValue(eCivic);
+ int iNewCivicValue = AI_civicValue((CivicTypes)iJ);
+
+ if (iNewCivicValue > iCurrentCivicValue)
+ {
+ iValue += std::min(2400, (2400 * (iNewCivicValue - iCurrentCivicValue)) / std::max(1, iCurrentCivicValue));
+ }
+
+ if (eCivic == GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivic())
+ {
+ iValue += 600;
+ }
+ }
+ }
+ }
+
+ if (iPathLength <= 2)
+ {
+ if (GC.getGameINLINE().countKnownTechNumTeams((TechTypes)iI) == 0)
+ {
+ int iReligionValue = 0;
+ int iPotentialReligions = 0;
+ for (iJ = 0; iJ < GC.getNumReligionInfos(); iJ++)
+ {
+ TechTypes eReligionTech = (TechTypes)GC.getReligionInfo((ReligionTypes)iJ).getTechPrereq();
+ if (kTeam.isHasTech(eReligionTech))
+ {
+ if (!(GC.getGameINLINE().isReligionSlotTaken((ReligionTypes)iJ)))
+ {
+ iPotentialReligions++;
+ }
+ }
+ if (eReligionTech == iI)
+ {
+ if (!(GC.getGameINLINE().isReligionSlotTaken((ReligionTypes)iJ)))
+ {
+ int iRoll = 2400;
+ if (!GC.getGame().isOption(GAMEOPTION_PICK_RELIGION))
+ {
+ ReligionTypes eFavorite = (ReligionTypes)GC.getLeaderHeadInfo(getLeaderType()).getFavoriteReligion();
+ if (eFavorite != NO_RELIGION)
+ {
+ if (iI == eFavorite)
+ {
+ iReligionValue += 1 + ((bAsync) ? GC.getASyncRand().get(1200, "AI Research Religion (Favorite) ASYNC") : GC.getGameINLINE().getSorenRandNum(1200, "AI Research Religion (Favorite)"));
+ iRandomMax += 1200;
+ }
+ else
+ {
+ iRoll *= 2;
+ iRoll /= 3;
+ }
+ }
+ }
+ iReligionValue += 1 + ((bAsync) ? GC.getASyncRand().get(iRoll, "AI Research Religion ASYNC") : GC.getGameINLINE().getSorenRandNum(iRoll, "AI Research Religion"));
+ iRandomMax += iRoll;
+ iRandomFactor += iReligionValue;
+
+ if (iPathLength < 2)
+ {
+ iReligionValue *= 3;
+ iReligionValue /= 2;
+ }
+ }
+ }
+ }
+
+ if (iReligionValue > 0)
+ {
+ if (AI_isDoStrategy(AI_STRATEGY_CULTURE1))
+ {
+ iReligionValue += 500;
+
+ if (countHolyCities() < 1)
+ {
+ iReligionValue += 1000;
+ }
+ }
+ else
+ {
+ iReligionValue /= (1 + countHolyCities() + ((iPotentialReligions > 0) ? 1 : 0));
+ }
+
+ if ((countTotalHasReligion() == 0) && (iPotentialReligions == 0))
+ {
+ iReligionValue *= 2;
+ iReligionValue += 500;
+ }
+
+ if (AI_isDoStrategy(AI_STRATEGY_DAGGER))
+ {
+ iReligionValue /= 2;
+ }
+ iValue += iReligionValue;
+ }
+
+ for (iJ = 0; iJ < GC.getNumCorporationInfos(); iJ++)
+ {
+ if (GC.getCorporationInfo((CorporationTypes)iJ).getTechPrereq() == iI)
+ {
+ if (!(GC.getGameINLINE().isCorporationFounded((CorporationTypes)iJ)))
+ {
+ iValue += 100 + ((bAsync) ? GC.getASyncRand().get(2400, "AI Research Corporation ASYNC") : GC.getGameINLINE().getSorenRandNum(2400, "AI Research Corporation"));
+ }
+ }
+ }
+
+ if (getTechFreeUnit((TechTypes) iI) != NO_UNIT)
+ {
+ int iGreatPeopleRandom = ((bAsync) ? GC.getASyncRand().get(3200, "AI Research Great People ASYNC") : GC.getGameINLINE().getSorenRandNum(3200, "AI Research Great People"));
+ iValue += iGreatPeopleRandom;
+
+ iRandomMax += 3200;
+ iRandomFactor += iGreatPeopleRandom;
+
+ if (bCapitalAlone)
+ {
+ iValue += 400;
+ }
+
+ iValue += 200;
+ }
+
+ iValue += (GC.getTechInfo((TechTypes)iI).getFirstFreeTechs() * (200 + ((bCapitalAlone) ? 400 : 0) + ((bAsync) ? GC.getASyncRand().get(3200, "AI Research Free Tech ASYNC") : GC.getGameINLINE().getSorenRandNum(3200, "AI Research Free Tech"))));
+ }
+ }
+
+ iValue += GC.getTechInfo((TechTypes)iI).getAIWeight();
+
+ if (!isHuman())
+ {
+ for (iJ = 0; iJ < GC.getNumFlavorTypes(); iJ++)
+ {
+ iValue += (AI_getFlavorValue((FlavorTypes)iJ) * GC.getTechInfo((TechTypes)iI).getFlavorValue(iJ) * 20);
+ }
+ }
+
+ if (GC.getTechInfo((TechTypes)iI).isRepeat())
+ {
+ iValue /= 10;
+ }
+
+ if (bIgnoreCost)
+ {
+ iValue *= (1 + (getResearchTurnsLeft(((TechTypes)iI), false)));
+ iValue /= 10;
+ }
+ else
+ {
+ if (iValue > 0)
+ {
+ //this stops quick speed messing up.... might want to adjust by other things too...
+ int iAdjustment = GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getResearchPercent();
+
+ int iTurnsLeft = getResearchTurnsLeftTimes100(((TechTypes)iI), false);
+ bool bCheapBooster = ((iTurnsLeft < (2 * iAdjustment)) && (0 == ((bAsync) ? GC.getASyncRand().get(5, "AI Choose Cheap Tech") : GC.getGameINLINE().getSorenRandNum(5, "AI Choose Cheap Tech"))));
+
+
+ iValue *= 100000;
+
+ iValue /= (iTurnsLeft + (bCheapBooster ? 1 : (5 * iAdjustment)));
+ }
+ }
+
+ //Tech Whore
+ if (!GC.getGameINLINE().isOption(GAMEOPTION_NO_TECH_TRADING))
+ {
+ if (GC.getTechInfo((TechTypes)iI).isTechTrading() || kTeam.isTechTrading())
+ {
+ if (((bAsync) ? GC.getASyncRand().get(100, "AI Tech Whore ASYNC") : GC.getGameINLINE().getSorenRandNum(100, "AI Tech Whore")) < (GC.getGameINLINE().isOption(GAMEOPTION_NO_TECH_BROKERING) ? 20 : 10))
+ {
+ int iKnownCount = 0;
+ int iPossibleKnownCount = 0;
+
+ for (int iTeam = 0; iTeam < MAX_CIV_TEAMS; iTeam++)
+ {
+ if (GET_TEAM((TeamTypes)iTeam).isAlive())
+ {
+ if (GET_TEAM(getTeam()).isHasMet((TeamTypes)iTeam))
+ {
+ if (GET_TEAM((TeamTypes)iTeam).isHasTech((TechTypes)iI))
+ {
+ iKnownCount++;
+ }
+ }
+
+ iPossibleKnownCount++;
+ }
+ }
+
+ if (iKnownCount == 0)
+ {
+ if (iPossibleKnownCount > 2)
+ {
+ int iTradeModifier = std::min(150, 25 * (iPossibleKnownCount - 2));
+ iValue *= 100 + iTradeModifier;
+ iValue /= 100;
+ }
+ }
+ }
+ }
+ }
+
+ if (AI_isDoStrategy(AI_STRATEGY_CULTURE3))
+ {
+ int iCVValue = AI_cultureVictoryTechValue((TechTypes)iI);
+ iValue *= (iCVValue + 10);
+ iValue /= ((iCVValue < 100) ? 400 : 100);
+ }
+
+ iValue = std::max(1, iValue);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestTech = ((TechTypes)iI);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ SAFE_DELETE_ARRAY(paiBonusClassRevealed);
+ SAFE_DELETE_ARRAY(paiBonusClassUnrevealed);
+ SAFE_DELETE_ARRAY(paiBonusClassHave);
+
+ return eBestTech;
+}
+
+
+void CvPlayerAI::AI_chooseFreeTech()
+{
+ TechTypes eBestTech;
+
+ clearResearchQueue();
+
+ CyArgsList argsList;
+ long lResult;
+ argsList.add(getID());
+ argsList.add(true);
+ lResult = -1;
+ gDLL->getPythonIFace()->callFunction(PYGameModule, "AI_chooseTech", argsList.makeFunctionArgs(), &lResult);
+ eBestTech = ((TechTypes)lResult);
+
+ if (eBestTech == NO_TECH)
+ {
+ eBestTech = AI_bestTech(1, true);
+ }
+
+ if (eBestTech != NO_TECH)
+ {
+ GET_TEAM(getTeam()).setHasTech(eBestTech, true, getID(), true, true);
+ }
+}
+
+
+void CvPlayerAI::AI_chooseResearch()
+{
+ TechTypes eBestTech;
+ int iI;
+
+ clearResearchQueue();
+
+ if (getCurrentResearch() == NO_TECH)
+ {
+ for (iI = 0; iI < MAX_PLAYERS; iI++)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isAlive())
+ {
+ if ((iI != getID()) && (GET_PLAYER((PlayerTypes)iI).getTeam() == getTeam()))
+ {
+ if (GET_PLAYER((PlayerTypes)iI).getCurrentResearch() != NO_TECH)
+ {
+ if (canResearch(GET_PLAYER((PlayerTypes)iI).getCurrentResearch()))
+ {
+ pushResearch(GET_PLAYER((PlayerTypes)iI).getCurrentResearch());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (getCurrentResearch() == NO_TECH)
+ {
+ CyArgsList argsList;
+ long lResult;
+ argsList.add(getID());
+ argsList.add(false);
+ lResult = -1;
+ gDLL->getPythonIFace()->callFunction(PYGameModule, "AI_chooseTech", argsList.makeFunctionArgs(), &lResult);
+ eBestTech = ((TechTypes)lResult);
+
+ if (eBestTech == NO_TECH)
+ {
+ int iAIResearchDepth;
+ iAIResearchDepth = AI_isDoStrategy(AI_STRATEGY_CULTURE3) ? 1 : 3;
+
+ eBestTech = AI_bestTech((isHuman()) ? 1 : iAIResearchDepth);
+ }
+
+ if (eBestTech != NO_TECH)
+ {
+ pushResearch(eBestTech);
+ }
+ }
+}
+
+
+DiploCommentTypes CvPlayerAI::AI_getGreeting(PlayerTypes ePlayer) const
+{
+ TeamTypes eWorstEnemy;
+
+ if (GET_PLAYER(ePlayer).getTeam() != getTeam())
+ {
+ eWorstEnemy = GET_TEAM(getTeam()).AI_getWorstEnemy();
+
+ if ((eWorstEnemy != NO_TEAM) && (eWorstEnemy != GET_PLAYER(ePlayer).getTeam()) && GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isHasMet(eWorstEnemy) && (GC.getASyncRand().get(4) == 0))
+ {
+ if (GET_PLAYER(ePlayer).AI_hasTradedWithTeam(eWorstEnemy) && !atWar(GET_PLAYER(ePlayer).getTeam(), eWorstEnemy))
+ {
+ return (DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_WORST_ENEMY_TRADING");
+ }
+ else
+ {
+ return (DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_WORST_ENEMY");
+ }
+ }
+ else if ((getNumNukeUnits() > 0) && (GC.getASyncRand().get(4) == 0))
+ {
+ return (DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_NUKES");
+ }
+ else if ((GET_PLAYER(ePlayer).getPower() < getPower()) && AI_getAttitude(ePlayer) < ATTITUDE_PLEASED && (GC.getASyncRand().get(4) == 0))
+ {
+ return (DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_UNIT_BRAG");
+ }
+ }
+
+ return (DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_GREETINGS");
+}
+
+
+bool CvPlayerAI::AI_isWillingToTalk(PlayerTypes ePlayer) const
+{
+ FAssertMsg(getPersonalityType() != NO_LEADER, "getPersonalityType() is not expected to be equal with NO_LEADER");
+ FAssertMsg(ePlayer != getID(), "shouldn't call this function on ourselves");
+
+ if (GET_PLAYER(ePlayer).getTeam() == getTeam()
+ || GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(getTeam())
+ || GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()))
+ {
+ return true;
+ }
+
+ if (GET_TEAM(getTeam()).isHuman())
+ {
+ return false;
+ }
+
+ if (atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
+ {
+ int iRefuseDuration = (GC.getLeaderHeadInfo(getPersonalityType()).getRefuseToTalkWarThreshold() * ((GET_TEAM(getTeam()).AI_isChosenWar(GET_PLAYER(ePlayer).getTeam())) ? 2 : 1));
+
+ int iOurSuccess = 1 + GET_TEAM(getTeam()).AI_getWarSuccess(GET_PLAYER(ePlayer).getTeam());
+ int iTheirSuccess = 1 + GET_TEAM(GET_PLAYER(ePlayer).getTeam()).AI_getWarSuccess(getTeam());
+ if (iTheirSuccess > iOurSuccess * 2)
+ {
+ iRefuseDuration *= 20 + ((80 * iOurSuccess * 2) / iTheirSuccess);
+ iRefuseDuration /= 100;
+ }
+
+ if (GET_TEAM(getTeam()).AI_getAtWarCounter(GET_PLAYER(ePlayer).getTeam()) < iRefuseDuration)
+ {
+ return false;
+ }
+
+ if (GET_TEAM(getTeam()).isAVassal())
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (AI_getMemoryCount(ePlayer, MEMORY_STOPPED_TRADING_RECENT) > 0)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+// XXX what if already at war???
+// Returns true if the AI wants to sneak attack...
+bool CvPlayerAI::AI_demandRebukedSneak(PlayerTypes ePlayer) const
+{
+ FAssertMsg(!isHuman(), "isHuman did not return false as expected");
+ FAssertMsg(ePlayer != getID(), "shouldn't call this function on ourselves");
+
+ FAssert(!(GET_TEAM(getTeam()).isAVassal()));
+ FAssert(!(GET_TEAM(getTeam()).isHuman()));
+
+ if (GC.getGameINLINE().getSorenRandNum(100, "AI Demand Rebuked") < GC.getLeaderHeadInfo(getPersonalityType()).getDemandRebukedSneakProb())
+ {
+ if (GET_TEAM(getTeam()).getPower(true) > GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getDefensivePower())
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+// XXX what if already at war???
+// Returns true if the AI wants to declare war...
+bool CvPlayerAI::AI_demandRebukedWar(PlayerTypes ePlayer) const
+{
+ FAssertMsg(!isHuman(), "isHuman did not return false as expected");
+ FAssertMsg(ePlayer != getID(), "shouldn't call this function on ourselves");
+
+ FAssert(!(GET_TEAM(getTeam()).isAVassal()));
+ FAssert(!(GET_TEAM(getTeam()).isHuman()));
+
+ // needs to be async because it only happens on the computer of the player who is in diplomacy...
+ if (GC.getASyncRand().get(100, "AI Demand Rebuked ASYNC") < GC.getLeaderHeadInfo(getPersonalityType()).getDemandRebukedWarProb())
+ {
+ if (GET_TEAM(getTeam()).getPower(true) > GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getDefensivePower())
+ {
+ if (GET_TEAM(getTeam()).AI_isAllyLandTarget(GET_PLAYER(ePlayer).getTeam()))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+// XXX maybe make this a little looser (by time...)
+bool CvPlayerAI::AI_hasTradedWithTeam(TeamTypes eTeam) const
+{
+ int iI;
+
+ for (iI = 0; iI < MAX_PLAYERS; iI++)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isAlive())
+ {
+ if (GET_PLAYER((PlayerTypes)iI).getTeam() == eTeam)
+ {
+ if ((AI_getPeacetimeGrantValue((PlayerTypes)iI) + AI_getPeacetimeTradeValue((PlayerTypes)iI)) > 0)
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+// static
+AttitudeTypes CvPlayerAI::AI_getAttitudeFromValue(int iAttitudeVal)
+{
+ if (iAttitudeVal >= 10)
+ {
+ return ATTITUDE_FRIENDLY;
+ }
+ else if (iAttitudeVal >= 3)
+ {
+ return ATTITUDE_PLEASED;
+ }
+ else if (iAttitudeVal <= -10)
+ {
+ return ATTITUDE_FURIOUS;
+ }
+ else if (iAttitudeVal <= -3)
+ {
+ return ATTITUDE_ANNOYED;
+ }
+ else
+ {
+ return ATTITUDE_CAUTIOUS;
+ }
+}
+
+AttitudeTypes CvPlayerAI::AI_getAttitude(PlayerTypes ePlayer, bool bForced) const
+{
+ PROFILE_FUNC();
+
+ FAssertMsg(ePlayer != getID(), "shouldn't call this function on ourselves");
+
+ return (AI_getAttitudeFromValue(AI_getAttitudeVal(ePlayer, bForced)));
+}
+
+
+int CvPlayerAI::AI_getAttitudeVal(PlayerTypes ePlayer, bool bForced) const
+{
+ PROFILE_FUNC();
+
+ int iRankDifference;
+ int iAttitude;
+ int iI;
+
+ FAssertMsg(ePlayer != getID(), "shouldn't call this function on ourselves");
+
+ if (bForced)
+ {
+ if (getTeam() == GET_PLAYER(ePlayer).getTeam() || (GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()) && !GET_TEAM(getTeam()).isCapitulated()))
+ {
+ return 100;
+ }
+
+ if (isBarbarian() || GET_PLAYER(ePlayer).isBarbarian())
+ {
+ return -100;
+ }
+ }
+
+ iAttitude = GC.getLeaderHeadInfo(getPersonalityType()).getBaseAttitude();
+
+ iAttitude += GC.getHandicapInfo(GET_PLAYER(ePlayer).getHandicapType()).getAttitudeChange();
+
+// if (GC.getGameINLINE().isOption(GAMEOPTION_AGGRESSIVE_AI))
+// {
+// if (GET_PLAYER(ePlayer).isHuman())
+// {
+// iAttitude -= 2;
+// }
+// }
+
+ if (!(GET_PLAYER(ePlayer).isHuman()))
+ {
+ iAttitude += (4 - abs(AI_getPeaceWeight() - GET_PLAYER(ePlayer).AI_getPeaceWeight()));
+ iAttitude += std::min(GC.getLeaderHeadInfo(getPersonalityType()).getWarmongerRespect(), GC.getLeaderHeadInfo(GET_PLAYER(ePlayer).getPersonalityType()).getWarmongerRespect());
+ }
+
+ iAttitude -= std::max(0, (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getNumMembers() - GET_TEAM(getTeam()).getNumMembers()));
+
+ iRankDifference = (GC.getGameINLINE().getPlayerRank(getID()) - GC.getGameINLINE().getPlayerRank(ePlayer));
+
+ if (iRankDifference > 0)
+ {
+ iAttitude += ((GC.getLeaderHeadInfo(getPersonalityType()).getWorseRankDifferenceAttitudeChange() * iRankDifference) / (GC.getGameINLINE().countCivPlayersEverAlive() + 1));
+ }
+ else
+ {
+ iAttitude += ((GC.getLeaderHeadInfo(getPersonalityType()).getBetterRankDifferenceAttitudeChange() * -(iRankDifference)) / (GC.getGameINLINE().countCivPlayersEverAlive() + 1));
+ }
+
+ if ((GC.getGameINLINE().getPlayerRank(getID()) >= (GC.getGameINLINE().countCivPlayersEverAlive() / 2)) &&
+ (GC.getGameINLINE().getPlayerRank(ePlayer) >= (GC.getGameINLINE().countCivPlayersEverAlive() / 2)))
+ {
+ iAttitude++;
+ }
+
+ if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).AI_getWarSuccess(getTeam()) > GET_TEAM(getTeam()).AI_getWarSuccess(GET_PLAYER(ePlayer).getTeam()))
+ {
+ iAttitude += GC.getLeaderHeadInfo(getPersonalityType()).getLostWarAttitudeChange();
+ }
+
+ iAttitude += AI_getCloseBordersAttitude(ePlayer);
+ iAttitude += AI_getWarAttitude(ePlayer);
+ iAttitude += AI_getPeaceAttitude(ePlayer);
+ iAttitude += AI_getSameReligionAttitude(ePlayer);
+ iAttitude += AI_getDifferentReligionAttitude(ePlayer);
+ iAttitude += AI_getBonusTradeAttitude(ePlayer);
+ iAttitude += AI_getOpenBordersAttitude(ePlayer);
+ iAttitude += AI_getDefensivePactAttitude(ePlayer);
+ iAttitude += AI_getRivalDefensivePactAttitude(ePlayer);
+ iAttitude += AI_getRivalVassalAttitude(ePlayer);
+ iAttitude += AI_getShareWarAttitude(ePlayer);
+ iAttitude += AI_getFavoriteCivicAttitude(ePlayer);
+ iAttitude += AI_getTradeAttitude(ePlayer);
+ iAttitude += AI_getRivalTradeAttitude(ePlayer);
+
+ for (iI = 0; iI < NUM_MEMORY_TYPES; iI++)
+ {
+ iAttitude += AI_getMemoryAttitude(ePlayer, ((MemoryTypes)iI));
+ }
+
+ iAttitude += AI_getColonyAttitude(ePlayer);
+ iAttitude += AI_getAttitudeExtra(ePlayer);
+
+ return range(iAttitude, -100, 100);
+}
+
+
+int CvPlayerAI::AI_calculateStolenCityRadiusPlots(PlayerTypes ePlayer) const
+{
+ PROFILE_FUNC();
+
+ CvPlot* pLoopPlot;
+ int iCount;
+ int iI;
+
+ FAssert(ePlayer != getID());
+
+ iCount = 0;
+
+ for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
+ {
+ pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
+
+ if (pLoopPlot->getOwnerINLINE() == ePlayer)
+ {
+ if (pLoopPlot->isPlayerCityRadius(getID()))
+ {
+ iCount++;
+ }
+ }
+ }
+
+ return iCount;
+}
+
+
+int CvPlayerAI::AI_getCloseBordersAttitude(PlayerTypes ePlayer) const
+{
+ if (m_aiCloseBordersAttitudeCache[ePlayer] == MAX_INT)
+ {
+ int iPercent;
+
+ if (getTeam() == GET_PLAYER(ePlayer).getTeam() || GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()) || GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(getTeam()))
+ {
+ return 0;
+ }
+
+ iPercent = std::min(60, (AI_calculateStolenCityRadiusPlots(ePlayer) * 3));
+
+ if (GET_TEAM(getTeam()).AI_isLandTarget(GET_PLAYER(ePlayer).getTeam()))
+ {
+ iPercent += 40;
+ }
+
+ m_aiCloseBordersAttitudeCache[ePlayer] = ((GC.getLeaderHeadInfo(getPersonalityType()).getCloseBordersAttitudeChange() * iPercent) / 100);
+ }
+
+ return m_aiCloseBordersAttitudeCache[ePlayer];
+}
+
+
+int CvPlayerAI::AI_getWarAttitude(PlayerTypes ePlayer) const
+{
+ int iAttitudeChange;
+ int iAttitude;
+
+ iAttitude = 0;
+
+ if (atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
+ {
+ iAttitude -= 3;
+ }
+
+ if (GC.getLeaderHeadInfo(getPersonalityType()).getAtWarAttitudeDivisor() != 0)
+ {
+ iAttitudeChange = (GET_TEAM(getTeam()).AI_getAtWarCounter(GET_PLAYER(ePlayer).getTeam()) / GC.getLeaderHeadInfo(getPersonalityType()).getAtWarAttitudeDivisor());
+ iAttitude += range(iAttitudeChange, -(abs(GC.getLeaderHeadInfo(getPersonalityType()).getAtWarAttitudeChangeLimit())), abs(GC.getLeaderHeadInfo(getPersonalityType()).getAtWarAttitudeChangeLimit()));
+ }
+
+ return iAttitude;
+}
+
+
+int CvPlayerAI::AI_getPeaceAttitude(PlayerTypes ePlayer) const
+{
+ int iAttitudeChange;
+
+ if (GC.getLeaderHeadInfo(getPersonalityType()).getAtPeaceAttitudeDivisor() != 0)
+ {
+ iAttitudeChange = (GET_TEAM(getTeam()).AI_getAtPeaceCounter(GET_PLAYER(ePlayer).getTeam()) / GC.getLeaderHeadInfo(getPersonalityType()).getAtPeaceAttitudeDivisor());
+ return range(iAttitudeChange, -(abs(GC.getLeaderHeadInfo(getPersonalityType()).getAtPeaceAttitudeChangeLimit())), abs(GC.getLeaderHeadInfo(getPersonalityType()).getAtPeaceAttitudeChangeLimit()));
+ }
+
+ return 0;
+}
+
+
+int CvPlayerAI::AI_getSameReligionAttitude(PlayerTypes ePlayer) const
+{
+ int iAttitudeChange;
+ int iAttitude;
+
+ iAttitude = 0;
+
+ if ((getStateReligion() != NO_RELIGION) && (getStateReligion() == GET_PLAYER(ePlayer).getStateReligion()))
+ {
+ iAttitude += GC.getLeaderHeadInfo(getPersonalityType()).getSameReligionAttitudeChange();
+
+ if (hasHolyCity(getStateReligion()))
+ {
+ iAttitude++;
+ }
+
+ if (GC.getLeaderHeadInfo(getPersonalityType()).getSameReligionAttitudeDivisor() != 0)
+ {
+ iAttitudeChange = (AI_getSameReligionCounter(ePlayer) / GC.getLeaderHeadInfo(getPersonalityType()).getSameReligionAttitudeDivisor());
+ iAttitude += range(iAttitudeChange, -(abs(GC.getLeaderHeadInfo(getPersonalityType()).getSameReligionAttitudeChangeLimit())), abs(GC.getLeaderHeadInfo(getPersonalityType()).getSameReligionAttitudeChangeLimit()));
+ }
+ }
+
+ return iAttitude;
+}
+
+
+int CvPlayerAI::AI_getDifferentReligionAttitude(PlayerTypes ePlayer) const
+{
+ int iAttitudeChange;
+ int iAttitude;
+
+ iAttitude = 0;
+
+ if ((getStateReligion() != NO_RELIGION) && (GET_PLAYER(ePlayer).getStateReligion() != NO_RELIGION) && (getStateReligion() != GET_PLAYER(ePlayer).getStateReligion()))
+ {
+ iAttitude += GC.getLeaderHeadInfo(getPersonalityType()).getDifferentReligionAttitudeChange();
+
+ if (hasHolyCity(getStateReligion()))
+ {
+ iAttitude--;
+ }
+
+ if (GC.getLeaderHeadInfo(getPersonalityType()).getDifferentReligionAttitudeDivisor() != 0)
+ {
+ iAttitudeChange = (AI_getDifferentReligionCounter(ePlayer) / GC.getLeaderHeadInfo(getPersonalityType()).getDifferentReligionAttitudeDivisor());
+ iAttitude += range(iAttitudeChange, -(abs(GC.getLeaderHeadInfo(getPersonalityType()).getDifferentReligionAttitudeChangeLimit())), abs(GC.getLeaderHeadInfo(getPersonalityType()).getDifferentReligionAttitudeChangeLimit()));
+ }
+ }
+
+ return iAttitude;
+}
+
+
+int CvPlayerAI::AI_getBonusTradeAttitude(PlayerTypes ePlayer) const
+{
+ int iAttitudeChange;
+
+ if (!atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
+ {
+ if (GC.getLeaderHeadInfo(getPersonalityType()).getBonusTradeAttitudeDivisor() != 0)
+ {
+ iAttitudeChange = (AI_getBonusTradeCounter(ePlayer) / GC.getLeaderHeadInfo(getPersonalityType()).getBonusTradeAttitudeDivisor());
+ return range(iAttitudeChange, -(abs(GC.getLeaderHeadInfo(getPersonalityType()).getBonusTradeAttitudeChangeLimit())), abs(GC.getLeaderHeadInfo(getPersonalityType()).getBonusTradeAttitudeChangeLimit()));
+ }
+ }
+
+ return 0;
+}
+
+
+int CvPlayerAI::AI_getOpenBordersAttitude(PlayerTypes ePlayer) const
+{
+ int iAttitudeChange;
+
+ if (!atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
+ {
+ if (GC.getLeaderHeadInfo(getPersonalityType()).getOpenBordersAttitudeDivisor() != 0)
+ {
+ iAttitudeChange = (GET_TEAM(getTeam()).AI_getOpenBordersCounter(GET_PLAYER(ePlayer).getTeam()) / GC.getLeaderHeadInfo(getPersonalityType()).getOpenBordersAttitudeDivisor());
+ return range(iAttitudeChange, -(abs(GC.getLeaderHeadInfo(getPersonalityType()).getOpenBordersAttitudeChangeLimit())), abs(GC.getLeaderHeadInfo(getPersonalityType()).getOpenBordersAttitudeChangeLimit()));
+ }
+ }
+
+ return 0;
+}
+
+
+int CvPlayerAI::AI_getDefensivePactAttitude(PlayerTypes ePlayer) const
+{
+ int iAttitudeChange;
+
+ if (getTeam() != GET_PLAYER(ePlayer).getTeam() && (GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()) || GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(getTeam())))
+ {
+ return GC.getLeaderHeadInfo(getPersonalityType()).getDefensivePactAttitudeChangeLimit();
+ }
+
+ if (!atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
+ {
+ if (GC.getLeaderHeadInfo(getPersonalityType()).getDefensivePactAttitudeDivisor() != 0)
+ {
+ iAttitudeChange = (GET_TEAM(getTeam()).AI_getDefensivePactCounter(GET_PLAYER(ePlayer).getTeam()) / GC.getLeaderHeadInfo(getPersonalityType()).getDefensivePactAttitudeDivisor());
+ return range(iAttitudeChange, -(abs(GC.getLeaderHeadInfo(getPersonalityType()).getDefensivePactAttitudeChangeLimit())), abs(GC.getLeaderHeadInfo(getPersonalityType()).getDefensivePactAttitudeChangeLimit()));
+ }
+ }
+
+ return 0;
+}
+
+
+int CvPlayerAI::AI_getRivalDefensivePactAttitude(PlayerTypes ePlayer) const
+{
+ int iAttitude = 0;
+
+ if (getTeam() == GET_PLAYER(ePlayer).getTeam() || GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()) || GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(getTeam()))
+ {
+ return iAttitude;
+ }
+
+ if (!(GET_TEAM(getTeam()).isDefensivePact(GET_PLAYER(ePlayer).getTeam())))
+ {
+ iAttitude -= ((4 * GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getDefensivePactCount(GET_PLAYER(ePlayer).getTeam())) / std::max(1, (GC.getGameINLINE().countCivTeamsAlive() - 2)));
+ }
+
+ return iAttitude;
+}
+
+
+int CvPlayerAI::AI_getRivalVassalAttitude(PlayerTypes ePlayer) const
+{
+ int iAttitude = 0;
+
+ if (getTeam() == GET_PLAYER(ePlayer).getTeam() || GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()) || GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(getTeam()))
+ {
+ return iAttitude;
+ }
+
+ if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getVassalCount(getTeam()) > 0)
+ {
+ iAttitude -= (6 * GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getPower(true)) / std::max(1, GC.getGameINLINE().countTotalCivPower());
+ }
+
+ return iAttitude;
+}
+
+
+int CvPlayerAI::AI_getShareWarAttitude(PlayerTypes ePlayer) const
+{
+ int iAttitudeChange;
+ int iAttitude;
+
+ iAttitude = 0;
+
+ if (!atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
+ {
+ if (GET_TEAM(getTeam()).AI_shareWar(GET_PLAYER(ePlayer).getTeam()))
+ {
+ iAttitude += GC.getLeaderHeadInfo(getPersonalityType()).getShareWarAttitudeChange();
+ }
+
+ if (GC.getLeaderHeadInfo(getPersonalityType()).getShareWarAttitudeDivisor() != 0)
+ {
+ iAttitudeChange = (GET_TEAM(getTeam()).AI_getShareWarCounter(GET_PLAYER(ePlayer).getTeam()) / GC.getLeaderHeadInfo(getPersonalityType()).getShareWarAttitudeDivisor());
+ iAttitude += range(iAttitudeChange, -(abs(GC.getLeaderHeadInfo(getPersonalityType()).getShareWarAttitudeChangeLimit())), abs(GC.getLeaderHeadInfo(getPersonalityType()).getShareWarAttitudeChangeLimit()));
+ }
+ }
+
+ return iAttitude;
+}
+
+
+int CvPlayerAI::AI_getFavoriteCivicAttitude(PlayerTypes ePlayer) const
+{
+ int iAttitudeChange;
+
+ int iAttitude;
+
+ iAttitude = 0;
+
+ if (GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivic() != NO_CIVIC)
+ {
+ if (isCivic((CivicTypes)(GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivic())) && GET_PLAYER(ePlayer).isCivic((CivicTypes)(GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivic())))
+ {
+ iAttitude += GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivicAttitudeChange();
+
+ if (GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivicAttitudeDivisor() != 0)
+ {
+ iAttitudeChange = (AI_getFavoriteCivicCounter(ePlayer) / GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivicAttitudeDivisor());
+ iAttitude += range(iAttitudeChange, -(abs(GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivicAttitudeChangeLimit())), abs(GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivicAttitudeChangeLimit()));
+ }
+ }
+ }
+
+ return iAttitude;
+}
+
+
+int CvPlayerAI::AI_getTradeAttitude(PlayerTypes ePlayer) const
+{
+ // XXX human only?
+ return range(((AI_getPeacetimeGrantValue(ePlayer) + std::max(0, (AI_getPeacetimeTradeValue(ePlayer) - GET_PLAYER(ePlayer).AI_getPeacetimeTradeValue(getID())))) / ((GET_TEAM(getTeam()).AI_getHasMetCounter(GET_PLAYER(ePlayer).getTeam()) + 1) * 5)), 0, 4);
+}
+
+
+int CvPlayerAI::AI_getRivalTradeAttitude(PlayerTypes ePlayer) const
+{
+ // XXX human only?
+ return -(range(((GET_TEAM(getTeam()).AI_getEnemyPeacetimeGrantValue(GET_PLAYER(ePlayer).getTeam()) + (GET_TEAM(getTeam()).AI_getEnemyPeacetimeTradeValue(GET_PLAYER(ePlayer).getTeam()) / 3)) / ((GET_TEAM(getTeam()).AI_getHasMetCounter(GET_PLAYER(ePlayer).getTeam()) + 1) * 10)), 0, 4));
+}
+
+
+int CvPlayerAI::AI_getMemoryAttitude(PlayerTypes ePlayer, MemoryTypes eMemory) const
+{
+ return ((AI_getMemoryCount(ePlayer, eMemory) * GC.getLeaderHeadInfo(getPersonalityType()).getMemoryAttitudePercent(eMemory)) / 100);
+}
+
+int CvPlayerAI::AI_getColonyAttitude(PlayerTypes ePlayer) const
+{
+ int iAttitude = 0;
+
+ if (getParent() == ePlayer)
+ {
+ iAttitude += GC.getLeaderHeadInfo(getPersonalityType()).getFreedomAppreciation();
+ }
+
+ return iAttitude;
+}
+
+
+
+PlayerVoteTypes CvPlayerAI::AI_diploVote(const VoteSelectionSubData& kVoteData, VoteSourceTypes eVoteSource, bool bPropose)
+{
+ PROFILE_FUNC();
+
+ CivicTypes eBestCivic;
+ int iOpenCount;
+ int iClosedCount;
+ int iValue;
+ int iBestValue;
+ int iI;
+
+ VoteTypes eVote = kVoteData.eVote;
+
+ if (GC.getGameINLINE().isTeamVote(eVote))
+ {
+ if (GC.getGameINLINE().isTeamVoteEligible(getTeam(), eVoteSource))
+ {
+ return (PlayerVoteTypes)getTeam();
+ }
+
+ if (GC.getVoteInfo(eVote).isVictory())
+ {
+ iBestValue = 7;
+ }
+ else
+ {
+ iBestValue = 0;
+ }
+
+ PlayerVoteTypes eBestTeam = PLAYER_VOTE_ABSTAIN;
+
+ for (iI = 0; iI < MAX_TEAMS; iI++)
+ {
+ if (GET_TEAM((TeamTypes)iI).isAlive())
+ {
+ if (GC.getGameINLINE().isTeamVoteEligible((TeamTypes)iI, eVoteSource))
+ {
+ if (GET_TEAM(getTeam()).isVassal((TeamTypes)iI))
+ {
+ return (PlayerVoteTypes)iI;
+ }
+
+ iValue = GET_TEAM(getTeam()).AI_getAttitudeVal((TeamTypes)iI);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestTeam = (PlayerVoteTypes)iI;
+ }
+ }
+ }
+ }
+
+ return eBestTeam;
+ }
+ else
+ {
+ TeamTypes eSecretaryGeneral = GC.getGameINLINE().getSecretaryGeneral(eVoteSource);
+
+ if (!bPropose)
+ {
+ if (eSecretaryGeneral != NO_TEAM)
+ {
+ if (eSecretaryGeneral == getTeam() ||(GET_TEAM(getTeam()).AI_getAttitude(eSecretaryGeneral) == ATTITUDE_FRIENDLY))
+ {
+ return PLAYER_VOTE_YES;
+ }
+ }
+ }
+
+ bool bDefy = false;
+
+ bool bValid = true;
+
+ if (bValid)
+ {
+ for (iI = 0; iI < GC.getNumCivicInfos(); iI++)
+ {
+ if (GC.getVoteInfo(eVote).isForceCivic(iI))
+ {
+ if (!isCivic((CivicTypes)iI))
+ {
+ eBestCivic = AI_bestCivic((CivicOptionTypes)(GC.getCivicInfo((CivicTypes)iI).getCivicOptionType()));
+
+ if (eBestCivic != NO_CIVIC)
+ {
+ if (eBestCivic != ((CivicTypes)iI))
+ {
+ int iBestCivicValue = AI_civicValue(eBestCivic);
+ int iNewCivicValue = AI_civicValue((CivicTypes)iI);
+ if (iBestCivicValue > ((iNewCivicValue * 120) / 100))
+ {
+ bValid = false;
+ if (iBestCivicValue > ((iNewCivicValue * (140 + (GC.getGame().getSorenRandNum(120, "AI Erratic Defiance (Force Civic)"))) / 100)))
+ {
+ bDefy = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (bValid)
+ {
+ if (GC.getVoteInfo(eVote).getTradeRoutes() > 0)
+ {
+ if (getNumCities() > ((GC.getGameINLINE().getNumCities() * 2) / (GC.getGameINLINE().countCivPlayersAlive() + 1)))
+ {
+ bValid = false;
+ }
+ }
+ }
+
+ if (bValid)
+ {
+ if (GC.getVoteInfo(eVote).isNoNukes())
+ {
+ int iVoteBanThreshold = 0;
+ iVoteBanThreshold += GET_TEAM(getTeam()).getNukeInterception() / 3;
+ iVoteBanThreshold += GC.getLeaderHeadInfo(getPersonalityType()).getBuildUnitProb();
+ iVoteBanThreshold *= std::max(1, GC.getLeaderHeadInfo(getPersonalityType()).getWarmongerRespect());
+ if (GC.getGameINLINE().isOption(GAMEOPTION_AGGRESSIVE_AI))
+ {
+ iVoteBanThreshold *= 2;
+ }
+
+ bool bAnyHasSdi = false;
+ for (iI = 0; iI < MAX_TEAMS; iI++)
+ {
+ if (GET_TEAM((TeamTypes)iI).isAlive() && iI != getTeam())
+ {
+ if (GET_TEAM((TeamTypes)iI).getNukeInterception() > 0)
+ {
+ bAnyHasSdi = true;
+ break;
+ }
+ }
+ }
+
+ if (!bAnyHasSdi && GET_TEAM(getTeam()).getNukeInterception() > 0 && GET_TEAM(getTeam()).getNumNukeUnits() > 0)
+ {
+ iVoteBanThreshold *= 2;
+ }
+
+ bValid = (GC.getGameINLINE().getSorenRandNum(100, "AI nuke ban vote") > iVoteBanThreshold);
+
+ if (AI_isDoStrategy(AI_STRATEGY_OWABWNW))
+ {
+ bValid = false;
+ }
+ else if ((GET_TEAM(getTeam()).getNumNukeUnits() / std::max(1, GET_TEAM(getTeam()).getNumMembers())) < (GC.getGameINLINE().countTotalNukeUnits() / std::max(1, GC.getGameINLINE().countCivPlayersAlive())))
+ {
+ bValid = false;
+ }
+ if (!bValid && AI_getNumTrainAIUnits(UNITAI_ICBM) > 0)
+ {
+ if (GC.getGame().getSorenRandNum(AI_isDoStrategy(AI_STRATEGY_OWABWNW) ? 2 : 3, "AI Erratic Defiance (No Nukes)") == 0)
+ {
+ bDefy = true;
+ }
+ }
+ }
+ }
+
+ if (bValid)
+ {
+ if (GC.getVoteInfo(eVote).isFreeTrade())
+ {
+ iOpenCount = 0;
+ iClosedCount = 0;
+
+ for (iI = 0; iI < MAX_TEAMS; iI++)
+ {
+ if (GET_TEAM((TeamTypes)iI).isAlive())
+ {
+ if (iI != getTeam())
+ {
+ if (GET_TEAM(getTeam()).isOpenBorders((TeamTypes)iI))
+ {
+ iOpenCount += GET_TEAM((TeamTypes)iI).getNumCities();
+ }
+ else
+ {
+ iClosedCount += GET_TEAM((TeamTypes)iI).getNumCities();
+ }
+ }
+ }
+ }
+
+ if (iOpenCount >= (getNumCities() * getTradeRoutes()))
+ {
+ bValid = false;
+ }
+
+ if (iClosedCount == 0)
+ {
+ bValid = false;
+ }
+ }
+ }
+
+ if (bValid)
+ {
+ if (GC.getVoteInfo(eVote).isOpenBorders())
+ {
+ bValid = true;
+
+ for (iI = 0; iI < MAX_CIV_TEAMS; iI++)
+ {
+ if (iI != getTeam())
+ {
+ if (GET_TEAM((TeamTypes)iI).isVotingMember(eVoteSource))
+ {
+ if (NO_DENIAL != GET_TEAM(getTeam()).AI_openBordersTrade((TeamTypes)iI))
+ {
+ bValid = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if (GC.getVoteInfo(eVote).isDefensivePact())
+ {
+ bValid = true;
+
+ for (iI = 0; iI < MAX_CIV_TEAMS; iI++)
+ {
+ if (iI != getTeam())
+ {
+ if (GET_TEAM((TeamTypes)iI).isVotingMember(eVoteSource))
+ {
+ if (NO_DENIAL != GET_TEAM(getTeam()).AI_defensivePactTrade((TeamTypes)iI))
+ {
+ bValid = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if (GC.getVoteInfo(eVote).isForcePeace())
+ {
+ FAssert(kVoteData.ePlayer != NO_PLAYER);
+ TeamTypes ePeaceTeam = GET_PLAYER(kVoteData.ePlayer).getTeam();
+
+ int iWarsWinning = 0;
+ int iWarsLosing = 0;
+ int iChosenWar = 0;
+ //Are we winning wars?
+ for (iI = 0; iI < MAX_CIV_TEAMS; iI++)
+ {
+ if (GET_TEAM((TeamTypes)iI).isAlive())
+ {
+ if (iI != ePeaceTeam)
+ {
+ if (GET_TEAM((TeamTypes)iI).isAtWar(ePeaceTeam))
+ {
+ if (GET_TEAM((TeamTypes)iI).AI_getWarSuccess(ePeaceTeam) < GET_TEAM(ePeaceTeam).AI_getWarSuccess((TeamTypes)iI))
+ {
+ ++iWarsWinning;
+ }
+ else
+ {
+ ++iWarsLosing;
+ }
+
+ if (GET_TEAM(ePeaceTeam).AI_isChosenWar((TeamTypes)iI))
+ {
+ ++iChosenWar;
+ }
+ }
+ }
+ }
+ }
+
+ if (ePeaceTeam == getTeam())
+ {
+ if (iWarsLosing < iChosenWar)
+ {
+ bValid = false;
+ }
+ else
+ {
+ bValid = (iWarsWinning < iWarsLosing);
+ }
+ }
+ else if (eSecretaryGeneral == getTeam() && !bPropose)
+ {
+ bValid = true;
+ }
+ else if (GET_TEAM(ePeaceTeam).isAtWar(getTeam()))
+ {
+ bValid = (bPropose || NO_DENIAL == GET_TEAM(getTeam()).AI_makePeaceTrade(ePeaceTeam, eSecretaryGeneral));
+
+ if (bValid)
+ {
+ bValid = (iWarsWinning > iWarsLosing);
+ }
+ }
+ else
+ {
+ if (GET_TEAM(getTeam()).AI_getAttitude(ePeaceTeam) >= ATTITUDE_CAUTIOUS)
+ {
+ bValid = (iWarsLosing > iWarsWinning);
+ }
+ else
+ {
+ bValid = (iWarsWinning > iWarsLosing);
+ }
+ }
+
+ if (!bValid && iWarsWinning > 0)
+ {
+ if (GC.getGame().getSorenRandNum(2, "AI Erratic Defiance (Force Peace)") == 0)
+ {
+ bDefy = true;
+ }
+ }
+ }
+ else if (GC.getVoteInfo(eVote).isForceNoTrade())
+ {
+ FAssert(kVoteData.ePlayer != NO_PLAYER);
+ TeamTypes eEmbargoTeam = GET_PLAYER(kVoteData.ePlayer).getTeam();
+
+ if (eSecretaryGeneral == getTeam() && !bPropose)
+ {
+ bValid = true;
+ }
+ else if (eEmbargoTeam == getTeam())
+ {
+ bValid = false;
+ if (!isNoForeignTrade())
+ {
+ bDefy = true;
+ }
+ }
+ else if (canStopTradingWithTeam(eEmbargoTeam))
+ {
+ bValid = (NO_DENIAL == AI_stopTradingTrade(eEmbargoTeam, kVoteData.ePlayer));
+ if (bValid)
+ {
+ bValid = (GET_TEAM(getTeam()).AI_getAttitude(eEmbargoTeam) <= ATTITUDE_CAUTIOUS);
+ }
+ }
+ else
+ {
+ bValid = (GET_TEAM(getTeam()).AI_getAttitude(eEmbargoTeam) < ATTITUDE_CAUTIOUS);
+ }
+ }
+ else if (GC.getVoteInfo(eVote).isForceWar())
+ {
+ FAssert(kVoteData.ePlayer != NO_PLAYER);
+ TeamTypes eWarTeam = GET_PLAYER(kVoteData.ePlayer).getTeam();
+
+ if (eSecretaryGeneral == getTeam() && !bPropose)
+ {
+ bValid = true;
+ }
+ else if (eWarTeam == getTeam())
+ {
+ bValid = false;
+ }
+ else if (GET_TEAM(eWarTeam).isAtWar(getTeam()))
+ {
+ bValid = true;
+ }
+ else
+ {
+ bValid = (bPropose || NO_DENIAL == GET_TEAM(getTeam()).AI_declareWarTrade(eWarTeam, eSecretaryGeneral));
+ if (bValid)
+ {
+ bValid = (GET_TEAM(getTeam()).AI_getAttitude(eWarTeam) < ATTITUDE_CAUTIOUS);
+ }
+ }
+ }
+ else if (GC.getVoteInfo(eVote).isAssignCity())
+ {
+ bValid = false;
+
+ FAssert(kVoteData.ePlayer != NO_PLAYER);
+ CvPlayer& kPlayer = GET_PLAYER(kVoteData.ePlayer);
+ CvCity* pCity = kPlayer.getCity(kVoteData.iCityId);
+ if (NULL != pCity)
+ {
+ if (NO_PLAYER != kVoteData.eOtherPlayer && kVoteData.eOtherPlayer != pCity->getOwnerINLINE())
+ {
+ if ((!bPropose && eSecretaryGeneral == getTeam()) || kVoteData.eOtherPlayer == getID())
+ {
+ bValid = true;
+ }
+ else if (kVoteData.ePlayer == getID())
+ {
+ bValid = false;
+ if (GC.getGame().getSorenRandNum(3, "AI Erratic Defiance (Assign City)") == 0)
+ {
+ bDefy = true;
+ }
+ }
+ else
+ {
+ bValid = (AI_getAttitude(kVoteData.ePlayer) < AI_getAttitude(kVoteData.eOtherPlayer));
+ }
+ }
+ }
+ }
+ }
+
+ if (bDefy && canDefyResolution(eVoteSource, kVoteData))
+ {
+ return PLAYER_VOTE_NEVER;
+ }
+
+ return (bValid ? PLAYER_VOTE_YES : PLAYER_VOTE_NO);
+ }
+
+}
+
+int CvPlayerAI::AI_dealVal(PlayerTypes ePlayer, const CLinkList* pList, bool bIgnoreAnnual, int iChange) const
+{
+ CLLNode* pNode;
+ CvCity* pCity;
+ int iValue;
+
+ FAssertMsg(ePlayer != getID(), "shouldn't call this function on ourselves");
+
+ iValue = 0;
+
+ if (atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
+ {
+ iValue += GET_TEAM(getTeam()).AI_endWarVal(GET_PLAYER(ePlayer).getTeam());
+ }
+
+ for (pNode = pList->head(); pNode; pNode = pList->next(pNode))
+ {
+ FAssertMsg(!(pNode->m_data.m_bHidden), "(pNode->m_data.m_bHidden) did not return false as expected");
+
+ switch (pNode->m_data.m_eItemType)
+ {
+ case TRADE_TECHNOLOGIES:
+ iValue += GET_TEAM(getTeam()).AI_techTradeVal((TechTypes)(pNode->m_data.m_iData), GET_PLAYER(ePlayer).getTeam());
+ break;
+ case TRADE_RESOURCES:
+ if (!bIgnoreAnnual)
+ {
+ iValue += AI_bonusTradeVal(((BonusTypes)(pNode->m_data.m_iData)), ePlayer, iChange);
+ }
+ break;
+ case TRADE_CITIES:
+ pCity = GET_PLAYER(ePlayer).getCity(pNode->m_data.m_iData);
+ if (pCity != NULL)
+ {
+ iValue += AI_cityTradeVal(pCity);
+ }
+ break;
+ case TRADE_GOLD:
+ iValue += (pNode->m_data.m_iData * AI_goldTradeValuePercent()) / 100;
+ break;
+ case TRADE_GOLD_PER_TURN:
+ if (!bIgnoreAnnual)
+ {
+ iValue += AI_goldPerTurnTradeVal(pNode->m_data.m_iData);
+ }
+ break;
+ case TRADE_MAPS:
+ iValue += GET_TEAM(getTeam()).AI_mapTradeVal(GET_PLAYER(ePlayer).getTeam());
+ break;
+ case TRADE_SURRENDER:
+ if (!bIgnoreAnnual)
+ {
+ iValue += GET_TEAM(getTeam()).AI_surrenderTradeVal(GET_PLAYER(ePlayer).getTeam());
+ }
+ break;
+ case TRADE_VASSAL:
+ if (!bIgnoreAnnual)
+ {
+ iValue += GET_TEAM(getTeam()).AI_vassalTradeVal(GET_PLAYER(ePlayer).getTeam());
+ }
+ break;
+ case TRADE_OPEN_BORDERS:
+ iValue += GET_TEAM(getTeam()).AI_openBordersTradeVal(GET_PLAYER(ePlayer).getTeam());
+ break;
+ case TRADE_DEFENSIVE_PACT:
+ iValue += GET_TEAM(getTeam()).AI_defensivePactTradeVal(GET_PLAYER(ePlayer).getTeam());
+ break;
+ case TRADE_PEACE:
+ iValue += GET_TEAM(getTeam()).AI_makePeaceTradeVal(((TeamTypes)(pNode->m_data.m_iData)), GET_PLAYER(ePlayer).getTeam());
+ break;
+ case TRADE_WAR:
+ iValue += GET_TEAM(getTeam()).AI_declareWarTradeVal(((TeamTypes)(pNode->m_data.m_iData)), GET_PLAYER(ePlayer).getTeam());
+ break;
+ case TRADE_EMBARGO:
+ iValue += AI_stopTradingTradeVal(((TeamTypes)(pNode->m_data.m_iData)), ePlayer);
+ break;
+ case TRADE_CIVIC:
+ iValue += AI_civicTradeVal(((CivicTypes)(pNode->m_data.m_iData)), ePlayer);
+ break;
+ case TRADE_RELIGION:
+ iValue += AI_religionTradeVal(((ReligionTypes)(pNode->m_data.m_iData)), ePlayer);
+ break;
+ }
+ }
+
+ return iValue;
+}
+
+
+bool CvPlayerAI::AI_goldDeal(const CLinkList* pList) const
+{
+ CLLNode* pNode;
+
+ for (pNode = pList->head(); pNode; pNode = pList->next(pNode))
+ {
+ FAssert(!(pNode->m_data.m_bHidden));
+
+ switch (pNode->m_data.m_eItemType)
+ {
+ case TRADE_GOLD:
+ case TRADE_GOLD_PER_TURN:
+ return true;
+ break;
+ }
+ }
+
+ return false;
+}
+
+
+bool CvPlayerAI::AI_considerOffer(PlayerTypes ePlayer, const CLinkList* pTheirList, const CLinkList* pOurList, int iChange) const
+{
+ CLLNode* pNode;
+ int iThreshold;
+
+ FAssertMsg(ePlayer != getID(), "shouldn't call this function on ourselves");
+
+ if (AI_goldDeal(pTheirList) && AI_goldDeal(pOurList))
+ {
+ return false;
+ }
+
+ if (iChange > -1)
+ {
+ for (pNode = pOurList->head(); pNode; pNode = pOurList->next(pNode))
+ {
+ if (getTradeDenial(ePlayer, pNode->m_data) != NO_DENIAL)
+ {
+ return false;
+ }
+ }
+ }
+
+ if (GET_PLAYER(ePlayer).getTeam() == getTeam())
+ {
+ return true;
+ }
+
+ if ((pOurList->getLength() == 0) && (pTheirList->getLength() > 0))
+ {
+ return true;
+ }
+
+ int iOurValue = GET_PLAYER(ePlayer).AI_dealVal(getID(), pOurList, false, iChange);
+ int iTheirValue = AI_dealVal(ePlayer, pTheirList, false, iChange);
+
+ if (iOurValue > 0 && 0 == pTheirList->getLength() && 0 == iTheirValue)
+ {
+ if (GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()) && CvDeal::isVassalTributeDeal(pOurList))
+ {
+ if (AI_getAttitude(ePlayer, false) <= GC.getLeaderHeadInfo(getPersonalityType()).getVassalRefuseAttitudeThreshold()
+ && GET_TEAM(getTeam()).getAtWarCount(true) == 0
+ && GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getDefensivePactCount() == 0)
+ {
+ iOurValue *= (GET_TEAM(getTeam()).getPower(false) + 10);
+ iOurValue /= (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getPower(false) + 10);
+ }
+ else
+ {
+ return true;
+ }
+ }
+ else
+ {
+ if (AI_getAttitude(ePlayer) < ATTITUDE_PLEASED)
+ {
+ if (GET_TEAM(getTeam()).getPower(false) > ((GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getPower(false) * 4) / 3))
+ {
+ return false;
+ }
+ }
+
+ if (AI_getMemoryCount(ePlayer, MEMORY_MADE_DEMAND_RECENT) > 0)
+ {
+ return false;
+ }
+ }
+
+ iThreshold = (GET_TEAM(getTeam()).AI_getHasMetCounter(GET_PLAYER(ePlayer).getTeam()) + 50);
+
+ iThreshold *= 2;
+
+ if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).AI_isLandTarget(getTeam()))
+ {
+ iThreshold *= 3;
+ }
+
+ iThreshold *= (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getPower(false) + 100);
+ iThreshold /= (GET_TEAM(getTeam()).getPower(false) + 100);
+
+ iThreshold -= GET_PLAYER(ePlayer).AI_getPeacetimeGrantValue(getID());
+
+ return (iOurValue < iThreshold);
+ }
+
+ if (iChange < 0)
+ {
+ return (iTheirValue * 110 >= iOurValue * 100);
+ }
+
+ return (iTheirValue >= iOurValue);
+}
+
+
+bool CvPlayerAI::AI_counterPropose(PlayerTypes ePlayer, const CLinkList* pTheirList, const CLinkList* pOurList, CLinkList* pTheirInventory, CLinkList* pOurInventory, CLinkList* pTheirCounter, CLinkList* pOurCounter) const
+{
+ CLLNode* pNode;
+ CLLNode* pBestNode;
+ CLLNode* pGoldPerTurnNode;
+ CLLNode* pGoldNode;
+ bool* pabBonusDeal;
+ CvCity* pCity;
+ bool bTheirGoldDeal;
+ bool bOurGoldDeal;
+ int iHumanDealWeight;
+ int iAIDealWeight;
+ int iGoldData;
+ int iGoldWeight;
+ int iWeight;
+ int iBestWeight;
+ int iValue;
+ int iBestValue;
+ int iI;
+
+ bTheirGoldDeal = AI_goldDeal(pTheirList);
+ bOurGoldDeal = AI_goldDeal(pOurList);
+
+ if (bOurGoldDeal && bTheirGoldDeal)
+ {
+ return false;
+ }
+
+ pabBonusDeal = new bool[GC.getNumBonusInfos()];
+
+ for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
+ {
+ pabBonusDeal[iI] = false;
+ }
+
+ pGoldPerTurnNode = NULL;
+ pGoldNode = NULL;
+
+ iHumanDealWeight = AI_dealVal(ePlayer, pTheirList);
+ iAIDealWeight = GET_PLAYER(ePlayer).AI_dealVal(getID(), pOurList);
+
+ int iGoldValuePercent = AI_goldTradeValuePercent();
+
+ pTheirCounter->clear();
+ pOurCounter->clear();
+
+ if (iAIDealWeight > iHumanDealWeight)
+ {
+ if (atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
+ {
+ iBestValue = 0;
+ iBestWeight = 0;
+ pBestNode = NULL;
+
+ for (pNode = pTheirInventory->head(); pNode && iAIDealWeight > iHumanDealWeight; pNode = pTheirInventory->next(pNode))
+ {
+ if (!pNode->m_data.m_bOffering && !pNode->m_data.m_bHidden)
+ {
+ if (pNode->m_data.m_eItemType == TRADE_CITIES)
+ {
+ FAssert(GET_PLAYER(ePlayer).canTradeItem(getID(), pNode->m_data));
+
+ if (GET_PLAYER(ePlayer).getTradeDenial(getID(), pNode->m_data) == NO_DENIAL)
+ {
+ pCity = GET_PLAYER(ePlayer).getCity(pNode->m_data.m_iData);
+
+ if (pCity != NULL)
+ {
+ iWeight = AI_cityTradeVal(pCity);
+
+ if (iWeight > 0)
+ {
+ iValue = AI_targetCityValue(pCity, false);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ iBestWeight = iWeight;
+ pBestNode = pNode;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (pBestNode != NULL)
+ {
+ iHumanDealWeight += iBestWeight;
+ pTheirCounter->insertAtEnd(pBestNode->m_data);
+ }
+ }
+
+ for (pNode = pTheirInventory->head(); pNode && iAIDealWeight > iHumanDealWeight; pNode = pTheirInventory->next(pNode))
+ {
+ if (!pNode->m_data.m_bOffering && !pNode->m_data.m_bHidden)
+ {
+ FAssert(GET_PLAYER(ePlayer).canTradeItem(getID(), pNode->m_data));
+
+ if (GET_PLAYER(ePlayer).getTradeDenial(getID(), pNode->m_data) == NO_DENIAL)
+ {
+ switch (pNode->m_data.m_eItemType)
+ {
+ case TRADE_GOLD:
+ if (!bOurGoldDeal)
+ {
+ pGoldNode = pNode;
+ }
+ break;
+ case TRADE_GOLD_PER_TURN:
+ if (!bOurGoldDeal)
+ {
+ pGoldPerTurnNode = pNode;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ int iGoldWeight = iAIDealWeight - iHumanDealWeight;
+
+ if (iGoldWeight > 0)
+ {
+ if (pGoldNode)
+ {
+ iGoldData = iGoldWeight * 100;
+ iGoldData /= iGoldValuePercent;
+ if ((iGoldData * iGoldValuePercent) < iGoldWeight)
+ {
+ iGoldData++;
+ }
+ if (GET_PLAYER(ePlayer).AI_maxGoldTrade(getID()) >= iGoldData)
+ {
+ pGoldNode->m_data.m_iData = iGoldData;
+ iHumanDealWeight += (iGoldData * iGoldValuePercent) / 100;
+ pTheirCounter->insertAtEnd(pGoldNode->m_data);
+ pGoldNode = NULL;
+ }
+ }
+ }
+
+ for (pNode = pOurList->head(); pNode; pNode = pOurList->next(pNode))
+ {
+ FAssert(!(pNode->m_data.m_bHidden));
+
+ switch (pNode->m_data.m_eItemType)
+ {
+ case TRADE_RESOURCES:
+ pabBonusDeal[pNode->m_data.m_iData] = true;
+ break;
+ }
+ }
+
+ for (pNode = pTheirInventory->head(); pNode && iAIDealWeight > iHumanDealWeight; pNode = pTheirInventory->next(pNode))
+ {
+ if (!pNode->m_data.m_bOffering && !pNode->m_data.m_bHidden)
+ {
+ FAssert(GET_PLAYER(ePlayer).canTradeItem(getID(), pNode->m_data));
+
+ if (GET_PLAYER(ePlayer).getTradeDenial(getID(), pNode->m_data) == NO_DENIAL)
+ {
+ iWeight = 0;
+
+ switch (pNode->m_data.m_eItemType)
+ {
+ case TRADE_TECHNOLOGIES:
+ iWeight += GET_TEAM(getTeam()).AI_techTradeVal((TechTypes)(pNode->m_data.m_iData), GET_PLAYER(ePlayer).getTeam());
+ break;
+ case TRADE_RESOURCES:
+ if (!pabBonusDeal[pNode->m_data.m_iData])
+ {
+ if (GET_PLAYER(ePlayer).getNumTradeableBonuses((BonusTypes)(pNode->m_data.m_iData)) > 1)
+ {
+ if (GET_PLAYER(ePlayer).AI_corporationBonusVal((BonusTypes)(pNode->m_data.m_iData)) == 0)
+ {
+ iWeight += AI_bonusTradeVal(((BonusTypes)(pNode->m_data.m_iData)), ePlayer, 1);
+ pabBonusDeal[pNode->m_data.m_iData] = true;
+ }
+ }
+ }
+ break;
+ }
+
+ if (iWeight > 0)
+ {
+ iHumanDealWeight += iWeight;
+ pTheirCounter->insertAtEnd(pNode->m_data);
+ }
+ }
+ }
+ }
+
+ for (pNode = pTheirInventory->head(); pNode && iAIDealWeight > iHumanDealWeight; pNode = pTheirInventory->next(pNode))
+ {
+ if (!pNode->m_data.m_bOffering && !pNode->m_data.m_bHidden)
+ {
+ if (pNode->m_data.m_eItemType == TRADE_MAPS)
+ {
+ FAssert(GET_PLAYER(ePlayer).canTradeItem(getID(), pNode->m_data));
+
+ if (GET_PLAYER(ePlayer).getTradeDenial(getID(), pNode->m_data) == NO_DENIAL)
+ {
+ iWeight = GET_TEAM(getTeam()).AI_mapTradeVal(GET_PLAYER(ePlayer).getTeam());
+
+ if (iWeight > 0)
+ {
+ iHumanDealWeight += iWeight;
+ pTheirCounter->insertAtEnd(pNode->m_data);
+ }
+ }
+ }
+ }
+ }
+
+ iGoldWeight = iAIDealWeight - iHumanDealWeight;
+
+ if (iGoldWeight > 0)
+ {
+ if (pGoldNode)
+ {
+ iGoldData = iGoldWeight * 100;
+ iGoldData /= iGoldValuePercent;
+
+ if ((iGoldWeight * 100) > (iGoldData * iGoldValuePercent))
+ {
+ iGoldData++;
+ }
+
+ iGoldData = std::min(iGoldData, GET_PLAYER(ePlayer).AI_maxGoldTrade(getID()));
+
+ if (iGoldData > 0)
+ {
+ pGoldNode->m_data.m_iData = iGoldData;
+ iHumanDealWeight += (iGoldData * iGoldValuePercent) / 100;
+ pTheirCounter->insertAtEnd(pGoldNode->m_data);
+ pGoldNode = NULL;
+ }
+ }
+ }
+
+ if (iAIDealWeight > iHumanDealWeight)
+ {
+ if (pGoldPerTurnNode)
+ {
+ iGoldData = 0;
+
+ while (AI_goldPerTurnTradeVal(iGoldData) < (iAIDealWeight - iHumanDealWeight))
+ {
+ iGoldData++;
+ }
+
+ iGoldData = std::min(iGoldData, GET_PLAYER(ePlayer).AI_maxGoldPerTurnTrade(getID()));
+
+ if (iGoldData > 0)
+ {
+ pGoldPerTurnNode->m_data.m_iData = iGoldData;
+ iHumanDealWeight += AI_goldPerTurnTradeVal(pGoldPerTurnNode->m_data.m_iData);
+ pTheirCounter->insertAtEnd(pGoldPerTurnNode->m_data);
+ pGoldPerTurnNode = NULL;
+ }
+ }
+ }
+
+ for (pNode = pTheirInventory->head(); pNode && iAIDealWeight > iHumanDealWeight; pNode = pTheirInventory->next(pNode))
+ {
+ if (!pNode->m_data.m_bOffering && !pNode->m_data.m_bHidden)
+ {
+ if (pNode->m_data.m_eItemType == TRADE_RESOURCES)
+ {
+ FAssert(GET_PLAYER(ePlayer).canTradeItem(getID(), pNode->m_data));
+
+ if (GET_PLAYER(ePlayer).getTradeDenial(getID(), pNode->m_data) == NO_DENIAL)
+ {
+ iWeight = 0;
+
+ if (!pabBonusDeal[pNode->m_data.m_iData])
+ {
+ if (GET_PLAYER(ePlayer).getNumTradeableBonuses((BonusTypes)(pNode->m_data.m_iData)) > 0)
+ {
+ iWeight += AI_bonusTradeVal(((BonusTypes)(pNode->m_data.m_iData)), ePlayer, 1);
+ pabBonusDeal[pNode->m_data.m_iData] = true;
+ }
+ }
+
+ if (iWeight > 0)
+ {
+ iHumanDealWeight += iWeight;
+ pTheirCounter->insertAtEnd(pNode->m_data);
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (iHumanDealWeight > iAIDealWeight)
+ {
+ if (atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
+ {
+ bool bSurrender = false;
+ for (pNode = pOurInventory->head(); pNode; pNode = pOurInventory->next(pNode))
+ {
+ if (!pNode->m_data.m_bOffering && !pNode->m_data.m_bHidden)
+ {
+ if (pNode->m_data.m_eItemType == TRADE_SURRENDER)
+ {
+ if (getTradeDenial(ePlayer, pNode->m_data) == NO_DENIAL)
+ {
+ iAIDealWeight += GET_TEAM(GET_PLAYER(ePlayer).getTeam()).AI_surrenderTradeVal(getTeam());
+ pOurCounter->insertAtEnd(pNode->m_data);
+ bSurrender = true;
+ }
+ break;
+ }
+ }
+ }
+
+ if (!bSurrender)
+ {
+ for (pNode = pOurInventory->head(); pNode; pNode = pOurInventory->next(pNode))
+ {
+ if (!pNode->m_data.m_bOffering && !pNode->m_data.m_bHidden)
+ {
+ if (pNode->m_data.m_eItemType == TRADE_PEACE_TREATY)
+ {
+ pOurCounter->insertAtEnd(pNode->m_data);
+ break;
+ }
+ }
+ }
+ }
+
+ iBestValue = 0;
+ iBestWeight = 0;
+ pBestNode = NULL;
+
+ for (pNode = pOurInventory->head(); pNode && iHumanDealWeight > iAIDealWeight; pNode = pOurInventory->next(pNode))
+ {
+ if (!pNode->m_data.m_bOffering && !pNode->m_data.m_bHidden)
+ {
+ if (pNode->m_data.m_eItemType == TRADE_CITIES)
+ {
+ FAssert(canTradeItem(ePlayer, pNode->m_data));
+
+ if (getTradeDenial(ePlayer, pNode->m_data) == NO_DENIAL)
+ {
+ pCity = getCity(pNode->m_data.m_iData);
+
+ if (pCity != NULL)
+ {
+ iWeight = GET_PLAYER(ePlayer).AI_cityTradeVal(pCity);
+
+ if (iWeight > 0)
+ {
+ iValue = GET_PLAYER(ePlayer).AI_targetCityValue(pCity, false);
+
+ if (iValue > iBestValue)
+ {
+ if (iHumanDealWeight >= (iAIDealWeight + iWeight))
+ {
+ iBestValue = iValue;
+ iBestWeight = iWeight;
+ pBestNode = pNode;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (pBestNode != NULL)
+ {
+ iAIDealWeight += iBestWeight;
+ pOurCounter->insertAtEnd(pBestNode->m_data);
+ }
+ }
+
+ for (pNode = pOurInventory->head(); pNode && iHumanDealWeight > iAIDealWeight; pNode = pOurInventory->next(pNode))
+ {
+ if (!pNode->m_data.m_bOffering && !pNode->m_data.m_bHidden)
+ {
+ FAssert(canTradeItem(ePlayer, pNode->m_data));
+
+ if (getTradeDenial(ePlayer, pNode->m_data) == NO_DENIAL)
+ {
+ switch (pNode->m_data.m_eItemType)
+ {
+ case TRADE_GOLD:
+ if (!bTheirGoldDeal)
+ {
+ pGoldNode = pNode;
+ }
+ break;
+ case TRADE_GOLD_PER_TURN:
+ if (!bTheirGoldDeal)
+ {
+ pGoldPerTurnNode = pNode;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ iGoldWeight = iHumanDealWeight - iAIDealWeight;
+
+ if (iGoldWeight > 0)
+ {
+ if (pGoldNode)
+ {
+ int iGoldData = iGoldWeight * 100;
+ iGoldData /= iGoldValuePercent;
+
+ if (AI_maxGoldTrade(ePlayer) >= iGoldData)
+ {
+ pGoldNode->m_data.m_iData = iGoldData;
+ iAIDealWeight += ((iGoldData * iGoldValuePercent) / 100);
+ pOurCounter->insertAtEnd(pGoldNode->m_data);
+ pGoldNode = NULL;
+ }
+ }
+ }
+
+ for (pNode = pTheirList->head(); pNode; pNode = pTheirList->next(pNode))
+ {
+ FAssert(!(pNode->m_data.m_bHidden));
+
+ switch (pNode->m_data.m_eItemType)
+ {
+ case TRADE_RESOURCES:
+ pabBonusDeal[pNode->m_data.m_iData] = true;
+ break;
+ }
+ }
+
+ for (pNode = pOurInventory->head(); pNode && iHumanDealWeight > iAIDealWeight; pNode = pOurInventory->next(pNode))
+ {
+ if (!pNode->m_data.m_bOffering && !pNode->m_data.m_bHidden)
+ {
+ FAssert(canTradeItem(ePlayer, pNode->m_data));
+
+ if (getTradeDenial(ePlayer, pNode->m_data) == NO_DENIAL)
+ {
+ iWeight = 0;
+
+ switch (pNode->m_data.m_eItemType)
+ {
+ case TRADE_TECHNOLOGIES:
+ iWeight += GET_TEAM(GET_PLAYER(ePlayer).getTeam()).AI_techTradeVal((TechTypes)(pNode->m_data.m_iData), getTeam());
+ break;
+ case TRADE_RESOURCES:
+ if (!pabBonusDeal[pNode->m_data.m_iData])
+ {
+ if (getNumTradeableBonuses((BonusTypes)(pNode->m_data.m_iData)) > 1)
+ {
+ iWeight += GET_PLAYER(ePlayer).AI_bonusTradeVal(((BonusTypes)(pNode->m_data.m_iData)), getID(), 1);
+ pabBonusDeal[pNode->m_data.m_iData] = true;
+ }
+ }
+ break;
+ }
+
+ if (iWeight > 0)
+ {
+ if (iHumanDealWeight >= (iAIDealWeight + iWeight))
+ {
+ iAIDealWeight += iWeight;
+ pOurCounter->insertAtEnd(pNode->m_data);
+ }
+ }
+ }
+ }
+ }
+
+ for (pNode = pOurInventory->head(); pNode && iHumanDealWeight > iAIDealWeight; pNode = pOurInventory->next(pNode))
+ {
+ if (!pNode->m_data.m_bOffering && !pNode->m_data.m_bHidden)
+ {
+ if (pNode->m_data.m_eItemType == TRADE_MAPS)
+ {
+ FAssert(canTradeItem(ePlayer, pNode->m_data));
+
+ if (getTradeDenial(ePlayer, pNode->m_data) == NO_DENIAL)
+ {
+ iWeight = GET_TEAM(GET_PLAYER(ePlayer).getTeam()).AI_mapTradeVal(getTeam());
+
+ if (iWeight > 0)
+ {
+ if (iHumanDealWeight >= (iAIDealWeight + iWeight))
+ {
+ iAIDealWeight += iWeight;
+ pOurCounter->insertAtEnd(pNode->m_data);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ iGoldWeight = iHumanDealWeight - iAIDealWeight;
+ if (iGoldWeight > 0)
+ {
+ if (pGoldNode)
+ {
+ iGoldData = iGoldWeight * 100;
+ iGoldData /= AI_goldTradeValuePercent();
+
+ iGoldData = std::min(iGoldData, AI_maxGoldTrade(ePlayer));
+
+ if (iGoldData > 0)
+ {
+ pGoldNode->m_data.m_iData = iGoldData;
+ iAIDealWeight += (iGoldData * AI_goldTradeValuePercent()) / 100;
+ pOurCounter->insertAtEnd(pGoldNode->m_data);
+ pGoldNode = NULL;
+ }
+ }
+ }
+
+ if (iHumanDealWeight > iAIDealWeight)
+ {
+ if (pGoldPerTurnNode)
+ {
+ iGoldData = 0;
+
+ while (GET_PLAYER(ePlayer).AI_goldPerTurnTradeVal(iGoldData + 1) <= (iHumanDealWeight - iAIDealWeight))
+ {
+ iGoldData++;
+ }
+
+ iGoldData = std::min(iGoldData, AI_maxGoldPerTurnTrade(ePlayer));
+
+ if (iGoldData > 0)
+ {
+ pGoldPerTurnNode->m_data.m_iData = iGoldData;
+ iAIDealWeight += GET_PLAYER(ePlayer).AI_goldPerTurnTradeVal(pGoldPerTurnNode->m_data.m_iData);
+ pOurCounter->insertAtEnd(pGoldPerTurnNode->m_data);
+ pGoldPerTurnNode = NULL;
+ }
+ }
+ }
+ }
+
+ SAFE_DELETE_ARRAY(pabBonusDeal);
+
+ return ((iAIDealWeight <= iHumanDealWeight) && ((pOurList->getLength() > 0) || (pOurCounter->getLength() > 0) || (pTheirCounter->getLength() > 0)));
+}
+
+
+int CvPlayerAI::AI_maxGoldTrade(PlayerTypes ePlayer) const
+{
+ int iMaxGold;
+ int iResearchBuffer;
+
+ FAssert(ePlayer != getID());
+
+ if (isHuman() || (GET_PLAYER(ePlayer).getTeam() == getTeam()))
+ {
+ iMaxGold = getGold();
+ }
+ else
+ {
+ iMaxGold = getTotalPopulation();
+
+ iMaxGold *= (GET_TEAM(getTeam()).AI_getHasMetCounter(GET_PLAYER(ePlayer).getTeam()) + 10);
+
+ iMaxGold *= GC.getLeaderHeadInfo(getPersonalityType()).getMaxGoldTradePercent();
+ iMaxGold /= 100;
+
+ iMaxGold -= AI_getGoldTradedTo(ePlayer);
+
+ iResearchBuffer = -calculateGoldRate() * 12;
+ iResearchBuffer *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getResearchPercent();
+ iResearchBuffer /= 100;
+
+ iMaxGold = std::min(iMaxGold, getGold() - iResearchBuffer);
+
+ iMaxGold = std::min(iMaxGold, getGold());
+
+ iMaxGold -= (iMaxGold % GC.getDefineINT("DIPLOMACY_VALUE_REMAINDER"));
+ }
+
+ return std::max(0, iMaxGold);
+}
+
+
+int CvPlayerAI::AI_maxGoldPerTurnTrade(PlayerTypes ePlayer) const
+{
+ int iMaxGoldPerTurn;
+
+ FAssert(ePlayer != getID());
+
+ if (isHuman() || (GET_PLAYER(ePlayer).getTeam() == getTeam()))
+ {
+ iMaxGoldPerTurn = (calculateGoldRate() + (getGold() / GC.getDefineINT("PEACE_TREATY_LENGTH")));
+ }
+ else
+ {
+ iMaxGoldPerTurn = getTotalPopulation();
+
+ iMaxGoldPerTurn *= GC.getLeaderHeadInfo(getPersonalityType()).getMaxGoldPerTurnTradePercent();
+ iMaxGoldPerTurn /= 100;
+
+ iMaxGoldPerTurn += std::min(0, getGoldPerTurnByPlayer(ePlayer));
+ }
+
+ return std::max(0, std::min(iMaxGoldPerTurn, calculateGoldRate()));
+}
+
+
+int CvPlayerAI::AI_goldPerTurnTradeVal(int iGoldPerTurn) const
+{
+ int iValue = iGoldPerTurn * GC.getDefineINT("PEACE_TREATY_LENGTH");
+ iValue *= AI_goldTradeValuePercent();
+ iValue /= 100;
+
+ return iValue;
+}
+
+int CvPlayerAI::AI_bonusVal(BonusTypes eBonus, int iChange) const
+{
+ int iValue = 0;
+ int iBonusCount = getNumAvailableBonuses(eBonus);
+ if ((iChange == 0) || ((iChange == 1) && (iBonusCount == 0)) || ((iChange == -1) && (iBonusCount == 1)))
+ {
+ //This is assuming the none-to-one or one-to-none case.
+ iValue += AI_baseBonusVal(eBonus);
+ iValue += AI_corporationBonusVal(eBonus);
+ }
+ else
+ {
+ //This is basically the marginal value of an additional instance of a bonus.
+ iValue += AI_baseBonusVal(eBonus) / 5;
+ iValue += AI_corporationBonusVal(eBonus);
+ }
+ return iValue;
+}
+
+//Value sans corporation
+int CvPlayerAI::AI_baseBonusVal(BonusTypes eBonus) const
+{
+ PROFILE_FUNC();
+
+ //recalculate if not defined
+ if(m_aiBonusValue[eBonus] == -1)
+ {
+ PROFILE("CvPlayerAI::AI_baseBonusVal::recalculate");
+
+ UnitTypes eLoopUnit;
+ BuildingTypes eLoopBuilding;
+ int iDiff;
+ int iValue = 0;
+ int iTempValue;
+ int iI, iJ;
+
+ if (!GET_TEAM(getTeam()).isBonusObsolete(eBonus))
+ {
+ iValue += (GC.getBonusInfo(eBonus).getHappiness() * 100);
+ iValue += (GC.getBonusInfo(eBonus).getHealth() * 100);
+
+ CvTeam& kTeam = GET_TEAM(getTeam());
+
+ CvCity* pCapital = getCapitalCity();
+ int iCityCount = getNumCities();
+ int iCoastalCityCount = countNumCoastalCities();
+
+ // find the first coastal city
+ CvCity* pCoastalCity = NULL;
+ CvCity* pUnconnectedCoastalCity = NULL;
+ if (iCoastalCityCount > 0)
+ {
+ int iLoop;
+ for (CvCity* pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ if (pLoopCity->isCoastal(GC.getMIN_WATER_SIZE_FOR_OCEAN()))
+ {
+ if (pLoopCity->isConnectedToCapital(getID()))
+ {
+ pCoastalCity = pLoopCity;
+ break;
+ }
+ else if (pUnconnectedCoastalCity == NULL)
+ {
+ pUnconnectedCoastalCity = pLoopCity;
+ }
+ }
+ }
+ }
+ if (pCoastalCity == NULL && pUnconnectedCoastalCity != NULL)
+ {
+ pCoastalCity = pUnconnectedCoastalCity;
+ }
+
+
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ eLoopUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI)));
+
+ if (eLoopUnit != NO_UNIT)
+ {
+ CvUnitInfo& kLoopUnit = GC.getUnitInfo(eLoopUnit);
+
+ iTempValue = 0;
+
+ if (kLoopUnit.getPrereqAndBonus() == eBonus)
+ {
+ iTempValue += 50;
+ }
+
+ for (iJ = 0; iJ < GC.getNUM_UNIT_PREREQ_OR_BONUSES(); iJ++)
+ {
+ if (kLoopUnit.getPrereqOrBonuses(iJ) == eBonus)
+ {
+ iTempValue += 40;
+ }
+ }
+
+ iTempValue += kLoopUnit.getBonusProductionModifier(eBonus) / 10;
+
+ if (iTempValue > 0)
+ {
+ bool bIsWater = (kLoopUnit.getDomainType() == DOMAIN_SEA);
+
+ // if non-limited water unit, weight by coastal cities
+ if (bIsWater && !isLimitedUnitClass((UnitClassTypes)(kLoopUnit.getUnitClassType())))
+ {
+ iTempValue *= std::min(iCoastalCityCount * 2, iCityCount); // double coastal cities, cap at total cities
+ iTempValue /= std::max(1, iCityCount);
+ }
+
+ if (canTrain(eLoopUnit))
+ {
+ // is it a water unit and no coastal cities or our coastal city cannot build because its obsolete
+ if ((bIsWater && (pCoastalCity == NULL || (pCoastalCity->allUpgradesAvailable(eLoopUnit) != NO_UNIT))) ||
+ // or our capital cannot build because its obsolete (we can already build all its upgrades)
+ (pCapital != NULL && pCapital->allUpgradesAvailable(eLoopUnit) != NO_UNIT))
+ {
+ // its worthless
+ iTempValue = 2;
+ }
+ // otherwise, value units we could build if we had this bonus double
+ else
+ {
+ iTempValue *= 2;
+ }
+ }
+
+ if (kLoopUnit.getPrereqAndTech() != NO_TECH)
+ {
+ iDiff = abs(GC.getTechInfo((TechTypes)(kLoopUnit.getPrereqAndTech())).getEra() - getCurrentEra());
+
+ if (iDiff == 0)
+ {
+ iTempValue *= 3;
+ iTempValue /= 2;
+ }
+ else
+ {
+ iTempValue /= iDiff;
+ }
+ }
+
+ iValue += iTempValue;
+ }
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
+ {
+ eLoopBuilding = ((BuildingTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iI)));
+
+ if (eLoopBuilding != NO_BUILDING)
+ {
+ CvBuildingInfo& kLoopBuilding = GC.getBuildingInfo(eLoopBuilding);
+
+ iTempValue = 0;
+
+ if (kLoopBuilding.getPrereqAndBonus() == eBonus)
+ {
+ iTempValue += 30;
+ }
+
+ for (iJ = 0; iJ < GC.getNUM_BUILDING_PREREQ_OR_BONUSES(); iJ++)
+ {
+ if (kLoopBuilding.getPrereqOrBonuses(iJ) == eBonus)
+ {
+ iTempValue += 20;
+ }
+ }
+
+ iTempValue += kLoopBuilding.getBonusProductionModifier(eBonus) / 10;
+
+ if (kLoopBuilding.getPowerBonus() == eBonus)
+ {
+ iTempValue += 60;
+ }
+
+ for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
+ {
+ iTempValue += kLoopBuilding.getBonusYieldModifier(eBonus, iJ) / 2;
+ if (kLoopBuilding.getPowerBonus() == eBonus)
+ {
+ iTempValue += kLoopBuilding.getPowerYieldModifier(iJ);
+ }
+ }
+
+ {
+ // determine whether we have the tech for this building
+ bool bHasTechForBuilding = true;
+ if (!(kTeam.isHasTech((TechTypes)(kLoopBuilding.getPrereqAndTech()))))
+ {
+ bHasTechForBuilding = false;
+ }
+ for (int iPrereqIndex = 0; bHasTechForBuilding && iPrereqIndex < GC.getNUM_BUILDING_AND_TECH_PREREQS(); iPrereqIndex++)
+ {
+ if (kLoopBuilding.getPrereqAndTechs(iPrereqIndex) != NO_TECH)
+ {
+ if (!(kTeam.isHasTech((TechTypes)(kLoopBuilding.getPrereqAndTechs(iPrereqIndex)))))
+ {
+ bHasTechForBuilding = false;
+ }
+ }
+ }
+
+ bool bIsStateReligion = (((ReligionTypes) kLoopBuilding.getStateReligion()) != NO_RELIGION);
+
+ //check if function call is cached
+ bool bCanConstruct = canConstruct(eLoopBuilding, false, /*bTestVisible*/ true, /*bIgnoreCost*/ true);
+
+ // bCanNeverBuild when true is accurate, it may be false in some cases where we will never be able to build
+ bool bCanNeverBuild = (bHasTechForBuilding && !bCanConstruct && !bIsStateReligion);
+
+ // if we can never build this, it is worthless
+ if (bCanNeverBuild)
+ {
+ iTempValue = 0;
+ }
+ // double value if we can build it right now
+ else if (bCanConstruct)
+ {
+ iTempValue *= 2;
+ }
+
+ // if non-limited water building, weight by coastal cities
+ if (kLoopBuilding.isWater() && !isLimitedWonderClass((BuildingClassTypes)(kLoopBuilding.getBuildingClassType())))
+ {
+ iTempValue *= iCoastalCityCount;
+ iTempValue /= std::max(1, iCityCount/2);
+ }
+
+ if (kLoopBuilding.getPrereqAndTech() != NO_TECH)
+ {
+ iDiff = abs(GC.getTechInfo((TechTypes)(kLoopBuilding.getPrereqAndTech())).getEra() - getCurrentEra());
+
+ if (iDiff == 0)
+ {
+ iTempValue *= 3;
+ iTempValue /= 2;
+ }
+ else
+ {
+ iTempValue /= iDiff;
+ }
+ }
+
+ iValue += iTempValue;
+ }
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumProjectInfos(); iI++)
+ {
+ ProjectTypes eProject = (ProjectTypes) iI;
+ CvProjectInfo& kLoopProject = GC.getProjectInfo(eProject);
+ iTempValue = 0;
+
+ iTempValue += kLoopProject.getBonusProductionModifier(eBonus) / 10;
+
+ if (iTempValue > 0)
+ {
+ bool bMaxedOut = (GC.getGameINLINE().isProjectMaxedOut(eProject) || kTeam.isProjectMaxedOut(eProject));
+
+ if (bMaxedOut)
+ {
+ // project worthless
+ iTempValue = 0;
+ }
+ else if (canCreate(eProject))
+ {
+ iTempValue *= 2;
+ }
+
+ if (kLoopProject.getTechPrereq() != NO_TECH)
+ {
+ iDiff = abs(GC.getTechInfo((TechTypes)(kLoopProject.getTechPrereq())).getEra() - getCurrentEra());
+
+ if (iDiff == 0)
+ {
+ iTempValue *= 3;
+ iTempValue /= 2;
+ }
+ else
+ {
+ iTempValue /= iDiff;
+ }
+ }
+
+ iValue += iTempValue;
+ }
+ }
+
+ RouteTypes eBestRoute = getBestRoute();
+ for (iI = 0; iI < GC.getNumBuildInfos(); iI++)
+ {
+ RouteTypes eRoute = (RouteTypes)(GC.getBuildInfo((BuildTypes)iI).getRoute());
+
+ if (eRoute != NO_ROUTE)
+ {
+ iTempValue = 0;
+ if (GC.getRouteInfo(eRoute).getPrereqBonus() == eBonus)
+ {
+ iTempValue += 80;
+ }
+ for (iJ = 0; iJ < GC.getNUM_ROUTE_PREREQ_OR_BONUSES(); iJ++)
+ {
+ if (GC.getRouteInfo(eRoute).getPrereqOrBonus(iJ) == eBonus)
+ {
+ iTempValue += 40;
+ }
+ }
+ if ((eBestRoute != NO_ROUTE) && (GC.getRouteInfo(getBestRoute()).getValue() <= GC.getRouteInfo(eRoute).getValue()))
+ {
+ iValue += iTempValue;
+ }
+ else
+ {
+ iValue += iTempValue / 2;
+ }
+ }
+ }
+
+ // int iCorporationValue = AI_corporationBonusVal(eBonus);
+ // iValue += iCorporationValue;
+ //
+ // if (iCorporationValue <= 0 && getNumAvailableBonuses(eBonus) > 0)
+ // {
+ // iValue /= 3;
+ // }
+
+ iValue /= 10;
+ }
+
+
+ //clamp value non-negative
+ m_aiBonusValue[eBonus] = std::max(0, iValue);
+ }
+
+ return m_aiBonusValue[eBonus];
+}
+
+int CvPlayerAI::AI_corporationBonusVal(BonusTypes eBonus) const
+{
+ int iValue = 0;
+ int iCityCount = getNumCities();
+ iCityCount += iCityCount / 6 + 1;
+
+ for (int iCorporation = 0; iCorporation < GC.getNumCorporationInfos(); ++iCorporation)
+ {
+ int iCorpCount = getHasCorporationCount((CorporationTypes)iCorporation);
+ if (iCorpCount > 0)
+ {
+ int iNumCorpBonuses = 0;
+ iCorpCount += getNumCities() / 6 + 1;
+ CvCorporationInfo& kCorp = GC.getCorporationInfo((CorporationTypes)iCorporation);
+ for (int i = 0; i < GC.getNUM_CORPORATION_PREREQ_BONUSES(); ++i)
+ {
+ if (eBonus == kCorp.getPrereqBonus(i))
+ {
+ iValue += (50 * kCorp.getYieldProduced(YIELD_FOOD) * iCorpCount) / iCityCount;
+ iValue += (50 * kCorp.getYieldProduced(YIELD_PRODUCTION) * iCorpCount) / iCityCount;
+ iValue += (30 * kCorp.getYieldProduced(YIELD_COMMERCE) * iCorpCount) / iCityCount;
+
+ iValue += (30 * kCorp.getCommerceProduced(COMMERCE_GOLD) * iCorpCount) / iCityCount;
+ iValue += (30 * kCorp.getCommerceProduced(COMMERCE_RESEARCH) * iCorpCount) / iCityCount;
+ iValue += (12 * kCorp.getCommerceProduced(COMMERCE_CULTURE) * iCorpCount) / iCityCount;
+ iValue += (20 * kCorp.getCommerceProduced(COMMERCE_ESPIONAGE) * iCorpCount) / iCityCount;
+
+ //Disabled since you can't found/spread a corp unless there is already a bonus,
+ //and that bonus will provide the entirity of the bonusProduced benefit.
+
+ /*if (NO_BONUS != kCorp.getBonusProduced())
+ {
+ if (getNumAvailableBonuses((BonusTypes)kCorp.getBonusProduced()) == 0)
+ {
+ iBonusValue += (1000 * iCorpCount * AI_baseBonusVal((BonusTypes)kCorp.getBonusProduced())) / (10 * iCityCount);
+ }
+ }*/
+ }
+ }
+ }
+ }
+
+ iValue /= 100; //percent
+ iValue /= 10; //match AI_baseBonusVal
+
+ return iValue;
+}
+
+
+int CvPlayerAI::AI_bonusTradeVal(BonusTypes eBonus, PlayerTypes ePlayer, int iChange) const
+{
+ int iValue;
+
+ FAssertMsg(ePlayer != getID(), "shouldn't call this function on ourselves");
+
+ iValue = AI_bonusVal(eBonus, iChange);
+
+ iValue *= ((std::min(getNumCities(), GET_PLAYER(ePlayer).getNumCities()) + 3) * 30);
+ iValue /= 100;
+
+ iValue *= std::max(0, (GC.getBonusInfo(eBonus).getAITradeModifier() + 100));
+ iValue /= 100;
+
+ if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(getTeam()) && !GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isCapitulated())
+ {
+ iValue /= 2;
+ }
+
+ return (iValue * GC.getDefineINT("PEACE_TREATY_LENGTH"));
+}
+
+
+DenialTypes CvPlayerAI::AI_bonusTrade(BonusTypes eBonus, PlayerTypes ePlayer) const
+{
+ PROFILE_FUNC();
+
+ AttitudeTypes eAttitude;
+ bool bStrategic;
+ int iI, iJ;
+
+ FAssertMsg(ePlayer != getID(), "shouldn't call this function on ourselves");
+
+ if (isHuman() && GET_PLAYER(ePlayer).isHuman())
+ {
+ return NO_DENIAL;
+ }
+
+ if (GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()))
+ {
+ return NO_DENIAL;
+ }
+
+ if (atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
+ {
+ return NO_DENIAL;
+ }
+
+ if (GET_PLAYER(ePlayer).getTeam() == getTeam())
+ {
+ return NO_DENIAL;
+ }
+
+ if (GET_PLAYER(ePlayer).getNumAvailableBonuses(eBonus) > 0 && GET_PLAYER(ePlayer).AI_corporationBonusVal(eBonus) <= 0)
+ {
+ return (GET_PLAYER(ePlayer).isHuman() ? DENIAL_JOKING : DENIAL_NO_GAIN);
+ }
+
+ if (isHuman())
+ {
+ return NO_DENIAL;
+ }
+
+ if (GET_TEAM(getTeam()).AI_getWorstEnemy() == GET_PLAYER(ePlayer).getTeam())
+ {
+ return DENIAL_WORST_ENEMY;
+ }
+
+ if (AI_corporationBonusVal(eBonus) > 0)
+ {
+ return DENIAL_JOKING;
+ }
+
+ bStrategic = false;
+
+ for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
+ {
+ if (GC.getUnitInfo((UnitTypes) iI).getPrereqAndBonus() == eBonus)
+ {
+ bStrategic = true;
+ }
+
+ for (iJ = 0; iJ < GC.getNUM_UNIT_PREREQ_OR_BONUSES(); iJ++)
+ {
+ if (GC.getUnitInfo((UnitTypes) iI).getPrereqOrBonuses(iJ) == eBonus)
+ {
+ bStrategic = true;
+ }
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
+ {
+ if (GC.getBuildingInfo((BuildingTypes) iI).getPrereqAndBonus() == eBonus)
+ {
+ bStrategic = true;
+ }
+
+ for (iJ = 0; iJ < GC.getNUM_BUILDING_PREREQ_OR_BONUSES(); iJ++)
+ {
+ if (GC.getBuildingInfo((BuildingTypes) iI).getPrereqOrBonuses(iJ) == eBonus)
+ {
+ bStrategic = true;
+ }
+ }
+ }
+
+ // XXX marble and stone???
+
+ eAttitude = AI_getAttitude(ePlayer);
+
+ if (bStrategic)
+ {
+ if (eAttitude <= GC.getLeaderHeadInfo(getPersonalityType()).getStrategicBonusRefuseAttitudeThreshold())
+ {
+ return DENIAL_ATTITUDE;
+ }
+ }
+
+ if (GC.getBonusInfo(eBonus).getHappiness() > 0)
+ {
+ if (eAttitude <= GC.getLeaderHeadInfo(getPersonalityType()).getHappinessBonusRefuseAttitudeThreshold())
+ {
+ return DENIAL_ATTITUDE;
+ }
+ }
+
+ if (GC.getBonusInfo(eBonus).getHealth() > 0)
+ {
+ if (eAttitude <= GC.getLeaderHeadInfo(getPersonalityType()).getHealthBonusRefuseAttitudeThreshold())
+ {
+ return DENIAL_ATTITUDE;
+ }
+ }
+
+ return NO_DENIAL;
+}
+
+
+int CvPlayerAI::AI_cityTradeVal(CvCity* pCity) const
+{
+ CvPlot* pLoopPlot;
+ int iValue;
+ int iI;
+
+ FAssert(pCity->getOwnerINLINE() != getID());
+
+ iValue = 300;
+
+ iValue += (pCity->getPopulation() * 50);
+
+ iValue += (pCity->getCultureLevel() * 200);
+
+ iValue += (((((pCity->getPopulation() * 50) + GC.getGameINLINE().getElapsedGameTurns() + 100) * 4) * pCity->plot()->calculateCulturePercent(pCity->getOwnerINLINE())) / 100);
+
+ for (iI = 0; iI < NUM_CITY_PLOTS; iI++)
+ {
+ pLoopPlot = plotCity(pCity->getX_INLINE(), pCity->getY_INLINE(), iI);
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->getBonusType(getTeam()) != NO_BONUS)
+ {
+ iValue += (AI_bonusVal(pLoopPlot->getBonusType(getTeam())) * 10);
+ }
+ }
+ }
+
+ if (!(pCity->isEverOwned(getID())))
+ {
+ iValue *= 3;
+ iValue /= 2;
+ }
+
+ iValue -= (iValue % GC.getDefineINT("DIPLOMACY_VALUE_REMAINDER"));
+
+ if (isHuman())
+ {
+ return std::max(iValue, GC.getDefineINT("DIPLOMACY_VALUE_REMAINDER"));
+ }
+ else
+ {
+ return iValue;
+ }
+}
+
+
+DenialTypes CvPlayerAI::AI_cityTrade(CvCity* pCity, PlayerTypes ePlayer) const
+{
+ CvCity* pNearestCity;
+
+ FAssert(pCity->getOwnerINLINE() == getID());
+
+ //Plako for RtR mod 11.8.2015
+ if(GC.getGameINLINE().isOption(GAMEOPTION_NO_CITY_TRADING)) {
+
+ return DENIAL_TOO_MUCH;
+ }
+
+ if (pCity->getLiberationPlayer(false) == ePlayer)
+ {
+ return NO_DENIAL;
+ }
+
+ if (!(GET_PLAYER(ePlayer).isHuman()))
+ {
+ if (GET_PLAYER(ePlayer).getTeam() != getTeam())
+ {
+ if ((pCity->plot()->calculateCulturePercent(ePlayer) == 0) && !(pCity->isEverOwned(ePlayer)) && (GET_PLAYER(ePlayer).getNumCities() > 3))
+ {
+ if (GET_PLAYER(ePlayer).AI_isFinancialTrouble())
+ {
+ return DENIAL_UNKNOWN;
+ }
+
+ pNearestCity = GC.getMapINLINE().findCity(pCity->getX_INLINE(), pCity->getY_INLINE(), ePlayer, NO_TEAM, true, false, NO_TEAM, NO_DIRECTION, pCity);
+
+ if ((pNearestCity == NULL) || (plotDistance(pCity->getX_INLINE(), pCity->getY_INLINE(), pNearestCity->getX_INLINE(), pNearestCity->getY_INLINE()) > 9))
+ {
+ return DENIAL_UNKNOWN;
+ }
+ }
+ }
+ }
+
+ if (isHuman())
+ {
+ return NO_DENIAL;
+ }
+
+ if (atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
+ {
+ return NO_DENIAL;
+ }
+
+ if (GET_PLAYER(ePlayer).getTeam() != getTeam())
+ {
+ return DENIAL_NEVER;
+ }
+
+ if (pCity->calculateCulturePercent(getID()) > 50)
+ {
+ return DENIAL_TOO_MUCH;
+ }
+
+ return NO_DENIAL;
+}
+
+
+int CvPlayerAI::AI_stopTradingTradeVal(TeamTypes eTradeTeam, PlayerTypes ePlayer) const
+{
+ CvDeal* pLoopDeal;
+ int iModifier;
+ int iValue;
+ int iLoop;
+
+ FAssertMsg(ePlayer != getID(), "shouldn't call this function on ourselves");
+ FAssertMsg(GET_PLAYER(ePlayer).getTeam() != getTeam(), "shouldn't call this function on ourselves");
+ FAssertMsg(eTradeTeam != getTeam(), "shouldn't call this function on ourselves");
+ FAssertMsg(GET_TEAM(eTradeTeam).isAlive(), "GET_TEAM(eWarTeam).isAlive is expected to be true");
+ FAssertMsg(!atWar(eTradeTeam, GET_PLAYER(ePlayer).getTeam()), "eTeam should be at peace with eWarTeam");
+
+ iValue = (50 + (GC.getGameINLINE().getGameTurn() / 2));
+ iValue += (GET_TEAM(eTradeTeam).getNumCities() * 5);
+
+ iModifier = 0;
+
+ switch (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).AI_getAttitude(eTradeTeam))
+ {
+ case ATTITUDE_FURIOUS:
+ break;
+
+ case ATTITUDE_ANNOYED:
+ iModifier += 25;
+ break;
+
+ case ATTITUDE_CAUTIOUS:
+ iModifier += 50;
+ break;
+
+ case ATTITUDE_PLEASED:
+ iModifier += 100;
+ break;
+
+ case ATTITUDE_FRIENDLY:
+ iModifier += 200;
+ break;
+
+ default:
+ FAssert(false);
+ break;
+ }
+
+ iValue *= std::max(0, (iModifier + 100));
+ iValue /= 100;
+
+ if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isOpenBorders(eTradeTeam))
+ {
+ iValue *= 2;
+ }
+
+ if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isDefensivePact(eTradeTeam))
+ {
+ iValue *= 3;
+ }
+
+ for(pLoopDeal = GC.getGameINLINE().firstDeal(&iLoop); pLoopDeal != NULL; pLoopDeal = GC.getGameINLINE().nextDeal(&iLoop))
+ {
+ if (pLoopDeal->isCancelable(getID()) && !(pLoopDeal->isPeaceDeal()))
+ {
+ if (GET_PLAYER(pLoopDeal->getFirstPlayer()).getTeam() == GET_PLAYER(ePlayer).getTeam())
+ {
+ if (pLoopDeal->getLengthSecondTrades() > 0)
+ {
+ iValue += (GET_PLAYER(pLoopDeal->getFirstPlayer()).AI_dealVal(pLoopDeal->getSecondPlayer(), pLoopDeal->getSecondTrades()) * ((pLoopDeal->getLengthFirstTrades() == 0) ? 2 : 1));
+ }
+ }
+
+ if (GET_PLAYER(pLoopDeal->getSecondPlayer()).getTeam() == GET_PLAYER(ePlayer).getTeam())
+ {
+ if (pLoopDeal->getLengthFirstTrades() > 0)
+ {
+ iValue += (GET_PLAYER(pLoopDeal->getSecondPlayer()).AI_dealVal(pLoopDeal->getFirstPlayer(), pLoopDeal->getFirstTrades()) * ((pLoopDeal->getLengthSecondTrades() == 0) ? 2 : 1));
+ }
+ }
+ }
+ }
+
+ if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(getTeam()))
+ {
+ iValue /= 2;
+ }
+
+ iValue -= (iValue % GC.getDefineINT("DIPLOMACY_VALUE_REMAINDER"));
+
+ if (isHuman())
+ {
+ return std::max(iValue, GC.getDefineINT("DIPLOMACY_VALUE_REMAINDER"));
+ }
+ else
+ {
+ return iValue;
+ }
+}
+
+
+DenialTypes CvPlayerAI::AI_stopTradingTrade(TeamTypes eTradeTeam, PlayerTypes ePlayer) const
+{
+ AttitudeTypes eAttitude;
+ AttitudeTypes eAttitudeThem;
+ int iI;
+
+ FAssertMsg(ePlayer != getID(), "shouldn't call this function on ourselves");
+ FAssertMsg(GET_PLAYER(ePlayer).getTeam() != getTeam(), "shouldn't call this function on ourselves");
+ FAssertMsg(eTradeTeam != getTeam(), "shouldn't call this function on ourselves");
+ FAssertMsg(GET_TEAM(eTradeTeam).isAlive(), "GET_TEAM(eTradeTeam).isAlive is expected to be true");
+ FAssertMsg(!atWar(getTeam(), eTradeTeam), "should be at peace with eTradeTeam");
+
+ if (isHuman())
+ {
+ return NO_DENIAL;
+ }
+
+ if (GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()))
+ {
+ return NO_DENIAL;
+ }
+
+ if (GET_TEAM(getTeam()).isVassal(eTradeTeam))
+ {
+ return DENIAL_POWER_THEM;
+ }
+
+ eAttitude = GET_TEAM(getTeam()).AI_getAttitude(GET_PLAYER(ePlayer).getTeam());
+
+ for (iI = 0; iI < MAX_PLAYERS; iI++)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isAlive())
+ {
+ if (GET_PLAYER((PlayerTypes)iI).getTeam() == getTeam())
+ {
+ if (eAttitude <= GC.getLeaderHeadInfo(GET_PLAYER((PlayerTypes)iI).getPersonalityType()).getStopTradingRefuseAttitudeThreshold())
+ {
+ return DENIAL_ATTITUDE;
+ }
+ }
+ }
+ }
+
+ eAttitudeThem = GET_TEAM(getTeam()).AI_getAttitude(eTradeTeam);
+
+ for (iI = 0; iI < MAX_PLAYERS; iI++)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isAlive())
+ {
+ if (GET_PLAYER((PlayerTypes)iI).getTeam() == getTeam())
+ {
+ if (eAttitudeThem > GC.getLeaderHeadInfo(GET_PLAYER((PlayerTypes)iI).getPersonalityType()).getStopTradingThemRefuseAttitudeThreshold())
+ {
+ return DENIAL_ATTITUDE_THEM;
+ }
+ }
+ }
+ }
+
+ return NO_DENIAL;
+}
+
+
+int CvPlayerAI::AI_civicTradeVal(CivicTypes eCivic, PlayerTypes ePlayer) const
+{
+ CivicTypes eBestCivic;
+ int iValue;
+
+ iValue = (2 * (getTotalPopulation() + GET_PLAYER(ePlayer).getTotalPopulation())); // XXX
+
+ eBestCivic = GET_PLAYER(ePlayer).AI_bestCivic((CivicOptionTypes)(GC.getCivicInfo(eCivic).getCivicOptionType()));
+
+ if (eBestCivic != NO_CIVIC)
+ {
+ if (eBestCivic != eCivic)
+ {
+ iValue += std::max(0, ((GET_PLAYER(ePlayer).AI_civicValue(eBestCivic) - GET_PLAYER(ePlayer).AI_civicValue(eCivic)) * 2));
+ }
+ }
+
+ if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(getTeam()))
+ {
+ iValue /= 2;
+ }
+
+ iValue -= (iValue % GC.getDefineINT("DIPLOMACY_VALUE_REMAINDER"));
+
+ if (isHuman())
+ {
+ return std::max(iValue, GC.getDefineINT("DIPLOMACY_VALUE_REMAINDER"));
+ }
+ else
+ {
+ return iValue;
+ }
+}
+
+
+DenialTypes CvPlayerAI::AI_civicTrade(CivicTypes eCivic, PlayerTypes ePlayer) const
+{
+ if (isHuman())
+ {
+ return NO_DENIAL;
+ }
+
+ if (GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()))
+ {
+ return NO_DENIAL;
+ }
+
+ if (atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
+ {
+ return NO_DENIAL;
+ }
+
+ if (GET_PLAYER(ePlayer).getTeam() == getTeam())
+ {
+ return NO_DENIAL;
+ }
+
+ if (getCivicPercentAnger(getCivics((CivicOptionTypes)(GC.getCivicInfo(eCivic).getCivicOptionType())),true) > getCivicPercentAnger(eCivic))
+ {
+ return DENIAL_ANGER_CIVIC;
+ }
+
+ CivicTypes eFavoriteCivic = (CivicTypes)GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivic();
+ if (eFavoriteCivic != NO_CIVIC)
+ {
+ if (isCivic(eFavoriteCivic) && (GC.getCivicInfo(eCivic).getCivicOptionType() == GC.getCivicInfo(eFavoriteCivic).getCivicOptionType()))
+ {
+ return DENIAL_FAVORITE_CIVIC;
+ }
+ }
+
+ if (GC.getCivilizationInfo(getCivilizationType()).getCivilizationInitialCivics(GC.getCivicInfo(eCivic).getCivicOptionType()) == eCivic)
+ {
+ return DENIAL_JOKING;
+ }
+
+ if (AI_getAttitude(ePlayer) <= GC.getLeaderHeadInfo(getPersonalityType()).getAdoptCivicRefuseAttitudeThreshold())
+ {
+ return DENIAL_ATTITUDE;
+ }
+
+ return NO_DENIAL;
+}
+
+
+int CvPlayerAI::AI_religionTradeVal(ReligionTypes eReligion, PlayerTypes ePlayer) const
+{
+ ReligionTypes eBestReligion;
+ int iValue;
+
+ iValue = (3 * (getTotalPopulation() + GET_PLAYER(ePlayer).getTotalPopulation())); // XXX
+
+ eBestReligion = GET_PLAYER(ePlayer).AI_bestReligion();
+
+ if (eBestReligion != NO_RELIGION)
+ {
+ if (eBestReligion != eReligion)
+ {
+ iValue += std::max(0, (GET_PLAYER(ePlayer).AI_religionValue(eBestReligion) - GET_PLAYER(ePlayer).AI_religionValue(eReligion)));
+ }
+ }
+
+ if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(getTeam()))
+ {
+ iValue /= 2;
+ }
+
+ iValue -= (iValue % GC.getDefineINT("DIPLOMACY_VALUE_REMAINDER"));
+
+ if (isHuman())
+ {
+ return std::max(iValue, GC.getDefineINT("DIPLOMACY_VALUE_REMAINDER"));
+ }
+ else
+ {
+ return iValue;
+ }
+}
+
+
+DenialTypes CvPlayerAI::AI_religionTrade(ReligionTypes eReligion, PlayerTypes ePlayer) const
+{
+ if (isHuman())
+ {
+ return NO_DENIAL;
+ }
+
+ if (GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()))
+ {
+ return NO_DENIAL;
+ }
+
+ if (atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
+ {
+ return NO_DENIAL;
+ }
+
+ if (GET_PLAYER(ePlayer).getTeam() == getTeam())
+ {
+ return NO_DENIAL;
+ }
+
+ if (getStateReligion() != NO_RELIGION)
+ {
+ if (getHasReligionCount(eReligion) < std::min((getHasReligionCount(getStateReligion()) - 1), (getNumCities() / 2)))
+ {
+ return DENIAL_MINORITY_RELIGION;
+ }
+ }
+
+ if (AI_getAttitude(ePlayer) <= GC.getLeaderHeadInfo(getPersonalityType()).getConvertReligionRefuseAttitudeThreshold())
+ {
+ return DENIAL_ATTITUDE;
+ }
+
+ return NO_DENIAL;
+}
+
+
+int CvPlayerAI::AI_unitImpassableCount(UnitTypes eUnit) const
+{
+ int iCount = 0;
+ for (int iI = 0; iI < GC.getNumTerrainInfos(); iI++)
+ {
+ if (GC.getUnitInfo(eUnit).getTerrainImpassable(iI))
+ {
+ TechTypes eTech = (TechTypes)GC.getUnitInfo(eUnit).getTerrainPassableTech(iI);
+ if (NO_TECH == eTech || !GET_TEAM(getTeam()).isHasTech(eTech))
+ {
+ iCount++;
+ }
+ }
+ }
+
+ for (int iI = 0; iI < GC.getNumFeatureInfos(); iI++)
+ {
+ if (GC.getUnitInfo(eUnit).getFeatureImpassable(iI))
+ {
+ TechTypes eTech = (TechTypes)GC.getUnitInfo(eUnit).getFeaturePassableTech(iI);
+ if (NO_TECH == eTech || !GET_TEAM(getTeam()).isHasTech(eTech))
+ {
+ iCount++;
+ }
+ }
+ }
+
+ return iCount;
+}
+
+
+int CvPlayerAI::AI_unitValue(UnitTypes eUnit, UnitAITypes eUnitAI, CvArea* pArea) const
+{
+ bool bValid;
+ int iNeededMissionaries;
+ int iCombatValue;
+ int iValue;
+ int iTempValue;
+ int iI;
+
+ FAssertMsg(eUnit != NO_UNIT, "Unit is not assigned a valid value");
+ FAssertMsg(eUnitAI != NO_UNITAI, "UnitAI is not assigned a valid value");
+
+ if (GC.getUnitInfo(eUnit).getDomainType() != AI_unitAIDomainType(eUnitAI))
+ {
+ if (eUnitAI != UNITAI_ICBM)//XXX
+ {
+ return 0;
+ }
+ }
+
+ if (GC.getUnitInfo(eUnit).getNotUnitAIType(eUnitAI))
+ {
+ return 0;
+ }
+
+ bValid = GC.getUnitInfo(eUnit).getUnitAIType(eUnitAI);
+
+ if (!bValid)
+ {
+ switch (eUnitAI)
+ {
+ case UNITAI_UNKNOWN:
+ break;
+
+ case UNITAI_ANIMAL:
+ if (GC.getUnitInfo(eUnit).isAnimal())
+ {
+ bValid = true;
+ }
+ break;
+
+ case UNITAI_SETTLE:
+ if (GC.getUnitInfo(eUnit).isFound())
+ {
+ bValid = true;
+ }
+ break;
+
+ case UNITAI_WORKER:
+ for (iI = 0; iI < GC.getNumBuildInfos(); iI++)
+ {
+ if (GC.getUnitInfo(eUnit).getBuilds(iI))
+ {
+ bValid = true;
+ break;
+ }
+ }
+ break;
+
+ case UNITAI_ATTACK:
+ if (GC.getUnitInfo(eUnit).getCombat() > 0)
+ {
+ if (!(GC.getUnitInfo(eUnit).isOnlyDefensive()))
+ {
+ bValid = true;
+ }
+ }
+ break;
+
+ case UNITAI_ATTACK_CITY:
+ if (GC.getUnitInfo(eUnit).getCombat() > 0)
+ {
+ if (!(GC.getUnitInfo(eUnit).isOnlyDefensive()))
+ {
+ if (!(GC.getUnitInfo(eUnit).isNoCapture()))
+ {
+ bValid = true;
+ }
+ }
+ }
+ break;
+
+ case UNITAI_COLLATERAL:
+ if (GC.getUnitInfo(eUnit).getCombat() > 0)
+ {
+ if (!(GC.getUnitInfo(eUnit).isOnlyDefensive()))
+ {
+ if (GC.getUnitInfo(eUnit).getCollateralDamage() > 0)
+ {
+ bValid = true;
+ }
+ }
+ }
+ break;
+
+ case UNITAI_PILLAGE:
+ if (GC.getUnitInfo(eUnit).getCombat() > 0)
+ {
+ if (!(GC.getUnitInfo(eUnit).isOnlyDefensive()))
+ {
+ bValid = true;
+ }
+ }
+ break;
+
+ case UNITAI_RESERVE:
+ if (GC.getUnitInfo(eUnit).getCombat() > 0)
+ {
+ if (!(GC.getUnitInfo(eUnit).isOnlyDefensive()))
+ {
+ bValid = true;
+ }
+ }
+ break;
+
+ case UNITAI_COUNTER:
+ if (GC.getUnitInfo(eUnit).getCombat() > 0)
+ {
+ if (!(GC.getUnitInfo(eUnit).isOnlyDefensive()))
+ {
+ if (GC.getUnitInfo(eUnit).getInterceptionProbability() > 0)
+ {
+ bValid = true;
+ }
+
+ if (!bValid)
+ {
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ if (GC.getUnitInfo(eUnit).getUnitClassAttackModifier(iI) > 0)
+ {
+ bValid = true;
+ break;
+ }
+
+ if (GC.getUnitInfo(eUnit).getTargetUnitClass(iI))
+ {
+ bValid = true;
+ break;
+ }
+ }
+ }
+
+ if (!bValid)
+ {
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); iI++)
+ {
+ if (GC.getUnitInfo(eUnit).getUnitCombatModifier(iI) > 0)
+ {
+ bValid = true;
+ break;
+ }
+
+ if (GC.getUnitInfo(eUnit).getTargetUnitCombat(iI))
+ {
+ bValid = true;
+ break;
+ }
+ }
+ }
+
+ if (!bValid)
+ {
+
+ for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
+ {
+ int iUnitClass = GC.getUnitInfo(eUnit).getUnitClassType();
+ if (NO_UNITCLASS != iUnitClass && GC.getUnitInfo((UnitTypes)iI).getDefenderUnitClass(iUnitClass))
+ {
+ bValid = true;
+ break;
+ }
+
+ int iUnitCombat = GC.getUnitInfo(eUnit).getUnitCombatType();
+ if (NO_UNITCOMBAT != iUnitCombat && GC.getUnitInfo((UnitTypes)iI).getDefenderUnitCombat(iUnitCombat))
+ {
+ bValid = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case UNITAI_CITY_DEFENSE:
+ if (GC.getUnitInfo(eUnit).getCombat() > 0)
+ {
+ if (!(GC.getUnitInfo(eUnit).isNoDefensiveBonus()))
+ {
+ if (GC.getUnitInfo(eUnit).getCityDefenseModifier() > 0)
+ {
+ bValid = true;
+ }
+ }
+ }
+ break;
+
+ case UNITAI_CITY_COUNTER:
+ if (GC.getUnitInfo(eUnit).getCombat() > 0)
+ {
+ if (!(GC.getUnitInfo(eUnit).isNoDefensiveBonus()))
+ {
+ if (GC.getUnitInfo(eUnit).getInterceptionProbability() > 0)
+ {
+ bValid = true;
+ }
+
+ if (!bValid)
+ {
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ if (GC.getUnitInfo(eUnit).getUnitClassDefenseModifier(iI) > 0)
+ {
+ bValid = true;
+ break;
+ }
+ }
+ }
+
+ if (!bValid)
+ {
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); iI++)
+ {
+ if (GC.getUnitInfo(eUnit).getUnitCombatModifier(iI) > 0)
+ {
+ bValid = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case UNITAI_CITY_SPECIAL:
+ break;
+
+ case UNITAI_PARADROP:
+ if (GC.getUnitInfo(eUnit).getDropRange() > 0)
+ {
+ bValid = true;
+ }
+ break;
+
+ case UNITAI_EXPLORE:
+ if (GC.getUnitInfo(eUnit).getCombat() > 0)
+ {
+ if (0 == AI_unitImpassableCount(eUnit))
+ {
+ bValid = true;
+ }
+ }
+ break;
+
+ case UNITAI_MISSIONARY:
+ if (pArea != NULL)
+ {
+ for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
+ {
+ if (GC.getUnitInfo(eUnit).getReligionSpreads((ReligionTypes)iI) > 0)
+ {
+ iNeededMissionaries = AI_neededMissionaries(pArea, ((ReligionTypes)iI));
+
+ if (iNeededMissionaries > 0)
+ {
+ if (iNeededMissionaries > countReligionSpreadUnits(pArea, ((ReligionTypes)iI)))
+ {
+ bValid = true;
+ break;
+ }
+ }
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumCorporationInfos(); iI++)
+ {
+ if (GC.getUnitInfo(eUnit).getCorporationSpreads((CorporationTypes)iI) > 0)
+ {
+ iNeededMissionaries = AI_neededExecutives(pArea, ((CorporationTypes)iI));
+
+ if (iNeededMissionaries > 0)
+ {
+ if (iNeededMissionaries > countCorporationSpreadUnits(pArea, ((CorporationTypes)iI)))
+ {
+ bValid = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case UNITAI_PROPHET:
+ case UNITAI_ARTIST:
+ case UNITAI_SCIENTIST:
+ case UNITAI_GENERAL:
+ case UNITAI_MERCHANT:
+ case UNITAI_ENGINEER:
+ case UNITAI_SPY:
+ break;
+
+ case UNITAI_ICBM:
+ if (GC.getUnitInfo(eUnit).getNukeRange() != -1)
+ {
+ bValid = true;
+ }
+ break;
+
+ case UNITAI_WORKER_SEA:
+ for (iI = 0; iI < GC.getNumBuildInfos(); iI++)
+ {
+ if (GC.getUnitInfo(eUnit).getBuilds(iI))
+ {
+ bValid = true;
+ break;
+ }
+ }
+ break;
+
+ case UNITAI_ATTACK_SEA:
+ if (GC.getUnitInfo(eUnit).getCombat() > 0)
+ {
+ if (GC.getUnitInfo(eUnit).getCargoSpace() == 0)
+ {
+ if (!(GC.getUnitInfo(eUnit).isInvisible()) && (GC.getUnitInfo(eUnit).getInvisibleType() == NO_INVISIBLE))
+ {
+ bValid = true;
+ }
+ }
+ }
+ break;
+
+ case UNITAI_RESERVE_SEA:
+ if (GC.getUnitInfo(eUnit).getCombat() > 0)
+ {
+ if (GC.getUnitInfo(eUnit).getCargoSpace() == 0)
+ {
+ bValid = true;
+ }
+ }
+ break;
+
+ case UNITAI_ESCORT_SEA:
+ if (GC.getUnitInfo(eUnit).getCombat() > 0)
+ {
+ if (GC.getUnitInfo(eUnit).getCargoSpace() == 0)
+ {
+ if (0 == AI_unitImpassableCount(eUnit))
+ {
+ bValid = true;
+ }
+ }
+ }
+ break;
+
+ case UNITAI_EXPLORE_SEA:
+ if (GC.getUnitInfo(eUnit).getCargoSpace() <= 1)
+ {
+ bValid = true;
+ }
+ break;
+
+ case UNITAI_ASSAULT_SEA:
+ case UNITAI_SETTLER_SEA:
+ if (GC.getUnitInfo(eUnit).getCargoSpace() > 0)
+ {
+ if (GC.getUnitInfo(eUnit).getSpecialCargo() == NO_SPECIALUNIT)
+ {
+ bValid = true;
+ }
+ }
+ break;
+
+ case UNITAI_MISSIONARY_SEA:
+ case UNITAI_SPY_SEA:
+ case UNITAI_CARRIER_SEA:
+ case UNITAI_MISSILE_CARRIER_SEA:
+ if (GC.getUnitInfo(eUnit).getCargoSpace() > 0)
+ {
+ if (GC.getUnitInfo(eUnit).getSpecialCargo() != NO_SPECIALUNIT)
+ {
+ for (int i = 0; i < NUM_UNITAI_TYPES; ++i)
+ {
+ if (GC.getSpecialUnitInfo((SpecialUnitTypes)GC.getUnitInfo(eUnit).getSpecialCargo()).isCarrierUnitAIType(eUnitAI))
+ {
+ bValid = true;
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case UNITAI_PIRATE_SEA:
+ if (GC.getUnitInfo(eUnit).isAlwaysHostile() && GC.getUnitInfo(eUnit).isHiddenNationality())
+ {
+ bValid = true;
+ }
+ break;
+
+ case UNITAI_ATTACK_AIR:
+ if (GC.getUnitInfo(eUnit).getAirCombat() > 0)
+ {
+ if (!GC.getUnitInfo(eUnit).isSuicide())
+ {
+ bValid = true;
+ }
+ }
+ break;
+
+ case UNITAI_DEFENSE_AIR:
+ if (GC.getUnitInfo(eUnit).getInterceptionProbability() > 0)
+ {
+ bValid = true;
+ }
+ break;
+
+ case UNITAI_CARRIER_AIR:
+ if (GC.getUnitInfo(eUnit).getAirCombat() > 0)
+ {
+ if (GC.getUnitInfo(eUnit).getInterceptionProbability() > 0)
+ {
+ bValid = true;
+ }
+ }
+ break;
+
+ case UNITAI_MISSILE_AIR:
+ if (GC.getUnitInfo(eUnit).getAirCombat() > 0)
+ {
+ if (GC.getUnitInfo(eUnit).isSuicide())
+ {
+ bValid = true;
+ }
+ }
+ break;
+
+ case UNITAI_ATTACK_CITY_LEMMING:
+ bValid = false;
+ break;
+
+ default:
+ FAssert(false);
+ break;
+ }
+ }
+
+ if (!bValid)
+ {
+ return 0;
+ }
+
+ iCombatValue = GC.getGameINLINE().AI_combatValue(eUnit);
+
+ iValue = 1;
+
+ iValue += GC.getUnitInfo(eUnit).getAIWeight();
+
+ int iFastMoverMultiplier;
+
+ switch (eUnitAI)
+ {
+ case UNITAI_UNKNOWN:
+ case UNITAI_ANIMAL:
+ break;
+
+ case UNITAI_SETTLE:
+ iValue += (GC.getUnitInfo(eUnit).getMoves() * 100);
+ break;
+
+ case UNITAI_WORKER:
+ for (iI = 0; iI < GC.getNumBuildInfos(); iI++)
+ {
+ if (GC.getUnitInfo(eUnit).getBuilds(iI))
+ {
+ iValue += 50;
+ }
+ }
+ iValue += (GC.getUnitInfo(eUnit).getMoves() * 100);
+ break;
+
+ case UNITAI_ATTACK:
+ iFastMoverMultiplier = AI_isDoStrategy(AI_STRATEGY_FASTMOVERS) ? 2 : 1;
+
+ iValue += iCombatValue;
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getMoves() * iFastMoverMultiplier) / 2);
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getWithdrawalProbability()) / 100);
+ if (GC.getUnitInfo(eUnit).getCombatLimit() < 100)
+ {
+ iValue -= (iCombatValue * (125 - GC.getUnitInfo(eUnit).getCombatLimit())) / 100;
+ }
+
+ break;
+
+ case UNITAI_ATTACK_CITY:
+ iFastMoverMultiplier = AI_isDoStrategy(AI_STRATEGY_FASTMOVERS) ? 4 : 1;
+
+ iTempValue = ((iCombatValue * iCombatValue) / 75) + (iCombatValue / 2);
+ iValue += iTempValue;
+ if (GC.getUnitInfo(eUnit).isNoDefensiveBonus())
+ {
+ iValue -= iTempValue / 2;
+ }
+ if (GC.getUnitInfo(eUnit).getDropRange() > 0)
+ {
+ iValue -= iTempValue / 2;
+ }
+ if (GC.getUnitInfo(eUnit).isFirstStrikeImmune())
+ {
+ iValue += (iTempValue * 8) / 100;
+ }
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getCityAttackModifier()) / 100);
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getCollateralDamage()) / 400);
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getMoves() * iFastMoverMultiplier) / 4);
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getWithdrawalProbability()) / 100);
+ if (!AI_isDoStrategy(AI_STRATEGY_AIR_BLITZ))
+ {
+ int iBombardValue = GC.getUnitInfo(eUnit).getBombardRate() * 4;
+ if (iBombardValue > 0)
+ {
+ //Percentage change
+ //Total Bombard == 0 : 600%
+ //Total Bombard == 100 : 200%
+ //Total Bombard == 200: 100%
+ //Total Bombard == 300: 50%
+ //Total Bombard == 400:
+ int iTotalBombardRate = AI_calculateTotalBombard(DOMAIN_LAND);
+ if (iTotalBombardRate < 100)
+ {
+ iBombardValue *= 4 * (200 - iTotalBombardRate);
+ iBombardValue /= 100;
+ }
+ else
+ {
+ iBombardValue *= 100;
+ iBombardValue /= std::min(400, iTotalBombardRate);
+ }
+ iValue += iBombardValue;
+ }
+ }
+
+ break;
+
+ case UNITAI_COLLATERAL:
+ iValue += iCombatValue;
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getCollateralDamage()) / 50);
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getMoves()) / 4);
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getWithdrawalProbability()) / 25);
+ iValue -= ((iCombatValue * GC.getUnitInfo(eUnit).getCityAttackModifier()) / 100);
+ break;
+
+ case UNITAI_PILLAGE:
+ iValue += iCombatValue;
+ iValue += (iCombatValue * GC.getUnitInfo(eUnit).getMoves());
+ break;
+
+ case UNITAI_RESERVE:
+ iValue += iCombatValue;
+ iValue -= ((iCombatValue * GC.getUnitInfo(eUnit).getCollateralDamage()) / 200);
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); iI++)
+ {
+// int iCombatModifier = GC.getUnitInfo(eUnit).getUnitCombatModifier(iI);
+// iCombatModifier = (iCombatModifier < 40) ? iCombatModifier : (40 + (iCombatModifier - 40) / 2);
+// iValue += ((iCombatValue * iCombatModifier) / 100);
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getUnitCombatModifier(iI) * AI_getUnitCombatWeight((UnitCombatTypes)iI)) / 12000);
+ }
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getMoves()) / 2);
+ break;
+
+ case UNITAI_COUNTER:
+ iValue += (iCombatValue / 2);
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getUnitClassAttackModifier(iI) * AI_getUnitClassWeight((UnitClassTypes)iI)) / 7500);
+ iValue += ((iCombatValue * (GC.getUnitInfo(eUnit).getTargetUnitClass(iI) ? 50 : 0)) / 100);
+ }
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); iI++)
+ {
+// int iCombatModifier = GC.getUnitInfo(eUnit).getUnitCombatModifier(iI);
+// iCombatModifier = (iCombatModifier < 40) ? iCombatModifier : (40 + (iCombatModifier - 40) / 2);
+// iValue += ((iCombatValue * iCombatModifier) / 100);
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getUnitCombatModifier(iI) * AI_getUnitCombatWeight((UnitCombatTypes)iI)) / 10000);
+ iValue += ((iCombatValue * (GC.getUnitInfo(eUnit).getTargetUnitCombat(iI) ? 50 : 0)) / 100);
+ }
+ for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
+ {
+ int eUnitClass = GC.getUnitInfo(eUnit).getUnitClassType();
+ if (NO_UNITCLASS != eUnitClass && GC.getUnitInfo((UnitTypes)iI).getDefenderUnitClass(eUnitClass))
+ {
+ iValue += (50 * iCombatValue) / 100;
+ }
+
+ int eUnitCombat = GC.getUnitInfo(eUnit).getUnitCombatType();
+ if (NO_UNITCOMBAT != eUnitCombat && GC.getUnitInfo((UnitTypes)iI).getDefenderUnitCombat(eUnitCombat))
+ {
+ iValue += (50 * iCombatValue) / 100;
+ }
+ }
+
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getMoves()) / 2);
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getWithdrawalProbability()) / 100);
+ iValue += (GC.getUnitInfo(eUnit).getInterceptionProbability() * 2);
+ break;
+
+ case UNITAI_CITY_DEFENSE:
+ iValue += ((iCombatValue * 2) / 3);
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getCityDefenseModifier()) / 75);
+ break;
+
+ case UNITAI_CITY_COUNTER:
+ case UNITAI_CITY_SPECIAL:
+ case UNITAI_PARADROP:
+ iValue += (iCombatValue / 2);
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getCityDefenseModifier()) / 100);
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getUnitClassAttackModifier(iI) * AI_getUnitClassWeight((UnitClassTypes)iI)) / 10000);
+ iValue += ((iCombatValue * (GC.getUnitInfo(eUnit).getDefenderUnitClass(iI) ? 50 : 0)) / 100);
+ }
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); iI++)
+ {
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getUnitCombatModifier(iI) * AI_getUnitCombatWeight((UnitCombatTypes)iI)) / 10000);
+ iValue += ((iCombatValue * (GC.getUnitInfo(eUnit).getDefenderUnitCombat(iI) ? 50 : 0)) / 100);
+ }
+ iValue += (GC.getUnitInfo(eUnit).getInterceptionProbability() * 3);
+ break;
+
+ case UNITAI_EXPLORE:
+ iValue += (iCombatValue / 2);
+ iValue += (GC.getUnitInfo(eUnit).getMoves() * 200);
+ if (GC.getUnitInfo(eUnit).isNoBadGoodies())
+ {
+ iValue += 100;
+ }
+ break;
+
+ case UNITAI_MISSIONARY:
+ iValue += (GC.getUnitInfo(eUnit).getMoves() * 100);
+ if (getStateReligion() != NO_RELIGION)
+ {
+ if (GC.getUnitInfo(eUnit).getReligionSpreads(getStateReligion()) > 0)
+ {
+ iValue += (5 * GC.getUnitInfo(eUnit).getReligionSpreads(getStateReligion())) / 2;
+ }
+ }
+ for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
+ {
+ if (GC.getUnitInfo(eUnit).getReligionSpreads((ReligionTypes)iI) && hasHolyCity((ReligionTypes)iI))
+ {
+ iValue += 80;
+ break;
+ }
+ }
+ if (AI_isDoStrategy(AI_STRATEGY_CULTURE2))
+ {
+ int iTempValue = 0;
+ for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
+ {
+ if (GC.getUnitInfo(eUnit).getReligionSpreads((ReligionTypes)iI))
+ {
+ iTempValue += (50 * getNumCities()) / (1 + getHasReligionCount((ReligionTypes)iI));
+ }
+ }
+ iValue += iTempValue;
+ }
+ for (iI = 0; iI < GC.getNumCorporationInfos(); ++iI)
+ {
+ if (hasHeadquarters((CorporationTypes)iI))
+ {
+ if (GC.getUnitInfo(eUnit).getCorporationSpreads(iI) > 0)
+ {
+ iValue += (5 * GC.getUnitInfo(eUnit).getCorporationSpreads(iI)) / 2;
+ iValue += 300 / std::max(1, pArea->countHasCorporation((CorporationTypes)iI, getID()));
+ }
+ }
+ }
+ break;
+
+ case UNITAI_PROPHET:
+ case UNITAI_ARTIST:
+ case UNITAI_SCIENTIST:
+ case UNITAI_GENERAL:
+ case UNITAI_MERCHANT:
+ case UNITAI_ENGINEER:
+ break;
+
+ case UNITAI_SPY:
+ iValue += (GC.getUnitInfo(eUnit).getMoves() * 100);
+ if (GC.getUnitInfo(eUnit).isSabotage())
+ {
+ iValue += 50;
+ }
+ if (GC.getUnitInfo(eUnit).isDestroy())
+ {
+ iValue += 50;
+ }
+ if (GC.getUnitInfo(eUnit).isCounterSpy())
+ {
+ iValue += 100;
+ }
+ break;
+
+ case UNITAI_ICBM:
+ if (GC.getUnitInfo(eUnit).getNukeRange() != -1)
+ {
+ iTempValue = 40 + (GC.getUnitInfo(eUnit).getNukeRange() * 40);
+ if (GC.getUnitInfo(eUnit).getAirRange() == 0)
+ {
+ iValue += iTempValue;
+ }
+ else
+ {
+ iValue += (iTempValue * std::min(10, GC.getUnitInfo(eUnit).getAirRange())) / 10;
+ }
+ iValue += (iTempValue * (60 + GC.getUnitInfo(eUnit).getEvasionProbability())) / 100;
+ }
+ break;
+
+ case UNITAI_WORKER_SEA:
+ for (iI = 0; iI < GC.getNumBuildInfos(); iI++)
+ {
+ if (GC.getUnitInfo(eUnit).getBuilds(iI))
+ {
+ iValue += 50;
+ }
+ }
+ iValue += (GC.getUnitInfo(eUnit).getMoves() * 100);
+ break;
+
+ case UNITAI_ATTACK_SEA:
+ iValue += iCombatValue;
+ iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getMoves()) / 2);
+ iValue += (GC.getUnitInfo(eUnit).getBombardRate() * 4);
+ break;
+
+ case UNITAI_RESERVE_SEA:
+ iValue += iCombatValue;
+ iValue += (iCombatValue * GC.getUnitInfo(eUnit).getMoves());
+ break;
+
+ case UNITAI_ESCORT_SEA:
+ iValue += iCombatValue;
+ iValue += (iCombatValue * GC.getUnitInfo(eUnit).getMoves());
+ iValue += (GC.getUnitInfo(eUnit).getInterceptionProbability() * 3);
+ if (GC.getUnitInfo(eUnit).getNumSeeInvisibleTypes() > 0)
+ {
+ iValue += 200;
+ }
+ break;
+
+ case UNITAI_EXPLORE_SEA:
+ {
+ int iExploreValue = 100;
+ if (pArea != NULL)
+ {
+ if (pArea->isWater())
+ {
+ if (pArea->getUnitsPerPlayer(BARBARIAN_PLAYER) > 0)
+ {
+ iExploreValue += (2 * iCombatValue);
+ }
+ }
+ }
+ iValue += (GC.getUnitInfo(eUnit).getMoves() * iExploreValue);
+ if (GC.getUnitInfo(eUnit).isAlwaysHostile())
+ {
+ iValue /= 2;
+ }
+ iValue /= (1 + AI_unitImpassableCount(eUnit));
+ }
+ break;
+
+ case UNITAI_ASSAULT_SEA:
+ case UNITAI_SETTLER_SEA:
+ case UNITAI_MISSIONARY_SEA:
+ case UNITAI_SPY_SEA:
+ iValue += (iCombatValue / 2);
+ iValue += (GC.getUnitInfo(eUnit).getMoves() * 200);
+ iValue += (GC.getUnitInfo(eUnit).getCargoSpace() * 300);
+ break;
+
+ case UNITAI_CARRIER_SEA:
+ iValue += iCombatValue;
+ iValue += (GC.getUnitInfo(eUnit).getMoves() * 50);
+ iValue += (GC.getUnitInfo(eUnit).getCargoSpace() * 400);
+ break;
+
+ case UNITAI_MISSILE_CARRIER_SEA:
+ iValue += iCombatValue * GC.getUnitInfo(eUnit).getMoves();
+ iValue += (25 + iCombatValue) * (3 + (GC.getUnitInfo(eUnit).getCargoSpace()));
+ break;
+
+ case UNITAI_PIRATE_SEA:
+ iValue += iCombatValue;
+ iValue += (iCombatValue * GC.getUnitInfo(eUnit).getMoves());
+ break;
+
+ case UNITAI_ATTACK_AIR:
+ iValue += iCombatValue;
+ iValue += (GC.getUnitInfo(eUnit).getCollateralDamage() * iCombatValue) / 100;
+ iValue += 4 * GC.getUnitInfo(eUnit).getBombRate();
+ iValue += (iCombatValue * (100 + 2 * GC.getUnitInfo(eUnit).getCollateralDamage()) * GC.getUnitInfo(eUnit).getAirRange()) / 100;
+ break;
+
+ case UNITAI_DEFENSE_AIR:
+ iValue += iCombatValue;
+ iValue += (GC.getUnitInfo(eUnit).getInterceptionProbability() * 3);
+ iValue += (GC.getUnitInfo(eUnit).getAirRange() * iCombatValue);
+ break;
+
+ case UNITAI_CARRIER_AIR:
+ iValue += (iCombatValue);
+ iValue += (GC.getUnitInfo(eUnit).getInterceptionProbability() * 2);
+ iValue += (GC.getUnitInfo(eUnit).getAirRange() * iCombatValue);
+ break;
+
+ case UNITAI_MISSILE_AIR:
+ iValue += iCombatValue;
+ iValue += 4 * GC.getUnitInfo(eUnit).getBombRate();
+ iValue += GC.getUnitInfo(eUnit).getAirRange() * iCombatValue;
+ break;
+
+ case UNITAI_ATTACK_CITY_LEMMING:
+ iValue += iCombatValue;
+ break;
+
+ default:
+ FAssert(false);
+ break;
+ }
+
+ if ((iCombatValue > 0) && ((eUnitAI == UNITAI_ATTACK) || (eUnitAI == UNITAI_ATTACK_CITY)))
+ {
+ if (pArea != NULL)
+ {
+ AreaAITypes eAreaAI = pArea->getAreaAIType(getTeam());
+ if (eAreaAI == AREAAI_ASSAULT || eAreaAI == AREAAI_ASSAULT_MASSING)
+ {
+ for (int iI = 0; iI < GC.getNumPromotionInfos(); iI++)
+ {
+ if (GC.getUnitInfo(eUnit).getFreePromotions(iI))
+ {
+ if (GC.getPromotionInfo((PromotionTypes)iI).isAmphib())
+ {
+ iValue *= 133;
+ iValue /= 100;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return std::max(0, iValue);
+}
+
+
+int CvPlayerAI::AI_totalUnitAIs(UnitAITypes eUnitAI) const
+{
+ return (AI_getNumTrainAIUnits(eUnitAI) + AI_getNumAIUnits(eUnitAI));
+}
+
+
+int CvPlayerAI::AI_totalAreaUnitAIs(CvArea* pArea, UnitAITypes eUnitAI) const
+{
+ return (pArea->getNumTrainAIUnits(getID(), eUnitAI) + pArea->getNumAIUnits(getID(), eUnitAI));
+}
+
+
+int CvPlayerAI::AI_totalWaterAreaUnitAIs(CvArea* pArea, UnitAITypes eUnitAI) const
+{
+ CvCity* pLoopCity;
+ int iCount;
+ int iLoop;
+ int iI;
+
+ iCount = AI_totalAreaUnitAIs(pArea, eUnitAI);
+
+ for (iI = 0; iI < MAX_PLAYERS; iI++)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isAlive())
+ {
+ for (pLoopCity = GET_PLAYER((PlayerTypes)iI).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER((PlayerTypes)iI).nextCity(&iLoop))
+ {
+ if (pLoopCity->waterArea() == pArea)
+ {
+ iCount += pLoopCity->plot()->plotCount(PUF_isUnitAIType, eUnitAI, -1, getID());
+
+ if (pLoopCity->getOwnerINLINE() == getID())
+ {
+ iCount += pLoopCity->getNumTrainUnitAI(eUnitAI);
+ }
+ }
+ }
+ }
+ }
+
+
+ return iCount;
+}
+
+
+int CvPlayerAI::AI_countCargoSpace(UnitAITypes eUnitAI) const
+{
+ CvUnit* pLoopUnit;
+ int iCount;
+ int iLoop;
+
+ iCount = 0;
+
+ for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
+ {
+ if (pLoopUnit->AI_getUnitAIType() == eUnitAI)
+ {
+ iCount += pLoopUnit->cargoSpace();
+ }
+ }
+
+ return iCount;
+}
+
+
+int CvPlayerAI::AI_neededExplorers(CvArea* pArea) const
+{
+ FAssert(pArea != NULL);
+ int iNeeded = 0;
+
+ if (pArea->isWater())
+ {
+ iNeeded = std::min(iNeeded + (pArea->getNumUnrevealedTiles(getTeam()) / 400), std::min(2, ((getNumCities() / 2) + 1)));
+ }
+ else
+ {
+ iNeeded = std::min(iNeeded + (pArea->getNumUnrevealedTiles(getTeam()) / 150), std::min(3, ((getNumCities() / 3) + 2)));
+ }
+
+ if (0 == iNeeded)
+ {
+ if ((GC.getGameINLINE().countCivTeamsAlive() - 1) > GET_TEAM(getTeam()).getHasMetCivCount(true))
+ {
+ if (pArea->isWater())
+ {
+ if (GC.getMap().findBiggestArea(true) == pArea)
+ {
+ iNeeded++;
+ }
+ }
+ else
+ {
+ if (getCapitalCity() != NULL && pArea->getID() == getCapitalCity()->getArea())
+ {
+ for (int iPlayer = 0; iPlayer < MAX_CIV_PLAYERS; iPlayer++)
+ {
+ CvPlayerAI& kPlayer = GET_PLAYER((PlayerTypes)iPlayer);
+ if (kPlayer.isAlive() && kPlayer.getTeam() != getTeam())
+ {
+ if (!GET_TEAM(getTeam()).isHasMet(kPlayer.getTeam()))
+ {
+ if (pArea->getCitiesPerPlayer(kPlayer.getID()) > 0)
+ {
+ iNeeded++;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return iNeeded;
+
+}
+
+
+int CvPlayerAI::AI_neededWorkers(CvArea* pArea) const
+{
+ CvCity* pLoopCity;
+ int iCount;
+ int iLoop;
+
+ iCount = countUnimprovedBonuses(pArea) * 2;
+
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ if (pLoopCity->getArea() == pArea->getID())
+ {
+ iCount += pLoopCity->AI_getWorkersNeeded() * 3;
+ }
+ }
+
+ if (iCount == 0)
+ {
+ return 0;
+ }
+
+ if (getBestRoute() != NO_ROUTE)
+ {
+ iCount += pArea->getCitiesPerPlayer(getID()) / 2;
+ }
+
+
+ iCount += 1;
+ iCount /= 3;
+ iCount = std::min(iCount, 3 * pArea->getCitiesPerPlayer(getID()));
+ iCount = std::min(iCount, (1 + getTotalPopulation()) / 2);
+
+ return std::max(1, iCount);
+
+}
+
+
+int CvPlayerAI::AI_neededMissionaries(CvArea* pArea, ReligionTypes eReligion) const
+{
+ PROFILE_FUNC();
+ int iCount;
+ bool bHoly, bState, bHolyState;
+ bool bCultureVictory = AI_isDoStrategy(AI_STRATEGY_CULTURE2);
+
+ bHoly = hasHolyCity(eReligion);
+ bState = (getStateReligion() == eReligion);
+ bHolyState = ((getStateReligion() != NO_RELIGION) && hasHolyCity(getStateReligion()));
+
+ iCount = 0;
+
+ //internal spread.
+ if (bCultureVictory || bState || bHoly)
+ {
+ iCount = std::max(iCount, (pArea->getCitiesPerPlayer(getID()) - pArea->countHasReligion(eReligion, getID())));
+ if (iCount > 0)
+ {
+ if (!bCultureVictory)
+ {
+ iCount = std::max(1, iCount / (bHoly ? 2 : 4));
+ }
+ return iCount;
+ }
+ }
+
+ //external spread.
+ if ((bHoly && bState) || (bHoly && !bHolyState && (getStateReligion() != NO_RELIGION)))
+ {
+ iCount += ((pArea->getNumCities() * 2) - (pArea->countHasReligion(eReligion) * 3));
+ iCount /= 8;
+
+ iCount = std::max(0, iCount);
+
+ if (AI_isPrimaryArea(pArea))
+ {
+ iCount++;
+ }
+ }
+
+
+ return iCount;
+}
+
+
+int CvPlayerAI::AI_neededExecutives(CvArea* pArea, CorporationTypes eCorporation) const
+{
+ if (!hasHeadquarters(eCorporation))
+ {
+ return 0;
+ }
+
+ int iCount = ((pArea->getCitiesPerPlayer(getID()) - pArea->countHasCorporation(eCorporation, getID())) * 2);
+ iCount += (pArea->getNumCities() - pArea->countHasCorporation(eCorporation));
+
+ iCount /= 3;
+
+ if (AI_isPrimaryArea(pArea))
+ {
+ ++iCount;
+ }
+
+ return iCount;
+}
+
+
+int CvPlayerAI::AI_adjacentPotentialAttackers(CvPlot* pPlot, bool bTestCanMove) const
+{
+ CLLNode* pUnitNode;
+ CvUnit* pLoopUnit;
+ CvPlot* pLoopPlot;
+ int iCount;
+ int iI;
+
+ iCount = 0;
+
+ for (iI = 0; iI < NUM_DIRECTION_TYPES; iI++)
+ {
+ pLoopPlot = plotDirection(pPlot->getX_INLINE(), pPlot->getY_INLINE(), ((DirectionTypes)iI));
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->area() == pPlot->area())
+ {
+ pUnitNode = pLoopPlot->headUnitNode();
+
+ while (pUnitNode != NULL)
+ {
+ pLoopUnit = ::getUnit(pUnitNode->m_data);
+ pUnitNode = pLoopPlot->nextUnitNode(pUnitNode);
+
+ if (pLoopUnit->getOwnerINLINE() == getID())
+ {
+ if (pLoopUnit->getDomainType() == ((pPlot->isWater()) ? DOMAIN_SEA : DOMAIN_LAND))
+ {
+ if (pLoopUnit->canAttack())
+ {
+ if (!bTestCanMove || pLoopUnit->canMove())
+ {
+ if (!(pLoopUnit->AI_isCityAIType()))
+ {
+ iCount++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return iCount;
+}
+
+
+int CvPlayerAI::AI_totalMissionAIs(MissionAITypes eMissionAI, CvSelectionGroup* pSkipSelectionGroup) const
+{
+ PROFILE_FUNC();
+
+ CvSelectionGroup* pLoopSelectionGroup;
+ int iCount;
+ int iLoop;
+
+ iCount = 0;
+
+ for(pLoopSelectionGroup = firstSelectionGroup(&iLoop); pLoopSelectionGroup; pLoopSelectionGroup = nextSelectionGroup(&iLoop))
+ {
+ if (pLoopSelectionGroup != pSkipSelectionGroup)
+ {
+ if (pLoopSelectionGroup->AI_getMissionAIType() == eMissionAI)
+ {
+ iCount += pLoopSelectionGroup->getNumUnits();
+ }
+ }
+ }
+
+ return iCount;
+}
+
+int CvPlayerAI::AI_missionaryValue(CvArea* pArea, ReligionTypes eReligion, PlayerTypes* peBestPlayer) const
+{
+ CvTeam& kTeam = GET_TEAM(getTeam());
+ CvGame& kGame = GC.getGame();
+
+ int iSpreadInternalValue = 100;
+ int iSpreadExternalValue = 0;
+ if (AI_isDoStrategy(AI_STRATEGY_CULTURE1))
+ {
+ iSpreadInternalValue += 500;
+ if (AI_isDoStrategy(AI_STRATEGY_CULTURE1))
+ {
+ iSpreadInternalValue += 1500;
+ if (AI_isDoStrategy(AI_STRATEGY_CULTURE1))
+ {
+ iSpreadInternalValue += 3000;
+ }
+ }
+ }
+ bool bStateReligion = (getStateReligion() == eReligion);
+ if (bStateReligion)
+ {
+ iSpreadInternalValue += 1000;
+ }
+ else
+ {
+ iSpreadInternalValue += (500 * getHasReligionCount(eReligion)) / std::max(1, getNumCities());
+ }
+
+ if (kTeam.hasHolyCity(eReligion))
+ {
+ iSpreadInternalValue += bStateReligion ? 1000 : 200;
+ iSpreadExternalValue += bStateReligion ? 1000 : 0;
+ if (kTeam.hasShrine(eReligion))
+ {
+ iSpreadInternalValue += bStateReligion ? 1000 : 500;
+ iSpreadExternalValue += bStateReligion ? 600 : 100;
+ int iGoldMultiplier = kGame.getHolyCity(eReligion)->getTotalCommerceRateModifier(COMMERCE_GOLD);
+ iSpreadInternalValue += 10 * std::max(0, (iGoldMultiplier - 100));
+ iSpreadExternalValue += 5 * std::max(0, (iGoldMultiplier - 150));
+ }
+ }
+
+ int iOurCitiesHave = 0;
+ int iOurCitiesCount = 0;
+
+ if (NULL == pArea)
+ {
+ iOurCitiesHave = kTeam.getHasReligionCount(eReligion);
+ iOurCitiesCount = kTeam.getNumCities();
+ }
+ else
+ {
+ iOurCitiesHave = pArea->countHasReligion(eReligion, getID());
+ iOurCitiesCount = pArea->getCitiesPerPlayer(getID());
+ }
+
+ if (iOurCitiesHave < iOurCitiesCount)
+ {
+ iSpreadInternalValue *= 50 + 50 * (iOurCitiesCount - iOurCitiesHave);
+ iSpreadInternalValue /= 100 * iOurCitiesCount;
+ }
+ else
+ {
+ iSpreadInternalValue = 0;
+ }
+
+ if (iSpreadExternalValue > 0)
+ {
+ int iBestPlayer = NO_PLAYER;
+ int iBestValue = 0;
+ for (int iPlayer = 0; iPlayer < MAX_PLAYERS; iPlayer++)
+ {
+ if (iPlayer != getID())
+ {
+ CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iPlayer);
+ if (kLoopPlayer.isAlive() && kLoopPlayer.getTeam() != getTeam() && kLoopPlayer.getNumCities() > 0)
+ {
+ if (GET_TEAM(kLoopPlayer.getTeam()).isOpenBorders(getTeam()))
+ {
+ int iCitiesCount = 0;
+ int iCitiesHave = 0;
+ int iMultiplier = AI_isDoStrategy(AI_STRATEGY_MISSIONARY) ? 60 : 25;
+ if (!kLoopPlayer.isNoNonStateReligionSpread() || (kLoopPlayer.getStateReligion() == eReligion))
+ {
+ if (NULL == pArea)
+ {
+ iCitiesCount += 1 + (kLoopPlayer.getNumCities() * 75) / 100;
+ iCitiesHave += std::min(iCitiesCount, kLoopPlayer.getHasReligionCount(eReligion));
+ }
+ else
+ {
+ int iPlayerSpreadPercent = (100 * kLoopPlayer.getHasReligionCount(eReligion)) / kLoopPlayer.getNumCities();
+ iCitiesCount += pArea->getCitiesPerPlayer((PlayerTypes)iPlayer);
+ iCitiesHave += std::min(iCitiesCount, (iCitiesCount * iPlayerSpreadPercent) / 75);
+ }
+ }
+
+ if (kLoopPlayer.getStateReligion() == NO_RELIGION)
+ {
+ if (kLoopPlayer.getStateReligionCount() > 0)
+ {
+ int iTotalReligions = kLoopPlayer.countTotalHasReligion();
+ iMultiplier += 100 * std::max(0, kLoopPlayer.getNumCities() - iTotalReligions);
+ iMultiplier += (iTotalReligions == 0) ? 100 : 0;
+ }
+ }
+
+ int iValue = (iMultiplier * iSpreadExternalValue * (iCitiesCount - iCitiesHave)) / std::max(1, iCitiesCount);
+ iValue /= 100;
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ iBestPlayer = iPlayer;
+ }
+ }
+ }
+ }
+ }
+
+ if (iBestValue > iSpreadInternalValue)
+ {
+ if (NULL != peBestPlayer)
+ {
+ *peBestPlayer = (PlayerTypes)iBestPlayer;
+ }
+ return iBestValue;
+ }
+
+ }
+
+ if (NULL != peBestPlayer)
+ {
+ *peBestPlayer = getID();
+ }
+ return iSpreadInternalValue;
+}
+
+int CvPlayerAI::AI_executiveValue(CvArea* pArea, CorporationTypes eCorporation, PlayerTypes* peBestPlayer) const
+{
+ CvTeam& kTeam = GET_TEAM(getTeam());
+ CvGame& kGame = GC.getGame();
+ CvCorporationInfo& kCorp = GC.getCorporationInfo(eCorporation);
+
+ int iSpreadInternalValue = 100;
+ int iSpreadExternalValue = 0;
+
+ if (kTeam.hasHeadquarters(eCorporation))
+ {
+ int iGoldMultiplier = kGame.getHeadquarters(eCorporation)->getTotalCommerceRateModifier(COMMERCE_GOLD);
+ iSpreadInternalValue += 10 * std::max(0, (iGoldMultiplier - 100));
+ iSpreadExternalValue += 15 * std::max(0, (iGoldMultiplier - 150));
+ }
+
+ int iOurCitiesHave = 0;
+ int iOurCitiesCount = 0;
+
+ if (NULL == pArea)
+ {
+ iOurCitiesHave = kTeam.getHasCorporationCount(eCorporation);
+ iOurCitiesCount = kTeam.getNumCities();
+ }
+ else
+ {
+ iOurCitiesHave = pArea->countHasCorporation(eCorporation, getID());
+ iOurCitiesCount = pArea->getCitiesPerPlayer(getID());
+ }
+
+ for (int iCorp = 0; iCorp < GC.getNumCorporationInfos(); iCorp++)
+ {
+ if (kGame.isCompetingCorporation(eCorporation, (CorporationTypes)iCorp))
+ {
+ if (NULL == pArea)
+ {
+ iOurCitiesHave += kTeam.getHasCorporationCount(eCorporation);
+ }
+ else
+ {
+ iOurCitiesHave += pArea->countHasCorporation(eCorporation, getID());
+ }
+ }
+ }
+
+ if (iOurCitiesHave >= iOurCitiesCount)
+ {
+ iSpreadInternalValue = 0;
+ if (iSpreadExternalValue = 0)
+ {
+ return 0;
+ }
+ }
+
+ int iBonusValue = 0;
+ CvCity* pCity = getCapitalCity();
+ if (pCity != NULL)
+ {
+ iBonusValue = AI_corporationValue(eCorporation, pCity);
+ iBonusValue /= 100;
+ }
+
+ for (int iPlayer = 0; iPlayer < MAX_PLAYERS; iPlayer++)
+ {
+ CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iPlayer);
+ if (kLoopPlayer.isAlive() && (kLoopPlayer.getNumCities() > 0))
+ {
+ if ((kLoopPlayer.getTeam() == getTeam()) || GET_TEAM(kLoopPlayer.getTeam()).isVassal(getTeam()))
+ {
+ if (kLoopPlayer.getHasCorporationCount(eCorporation) == 0)
+ {
+ iBonusValue += 1000;
+ }
+ }
+ }
+ }
+
+ if (iBonusValue == 0)
+ {
+ return 0;
+ }
+
+ iSpreadInternalValue += iBonusValue;
+
+ if (iSpreadExternalValue > 0)
+ {
+ int iBestPlayer = NO_PLAYER;
+ int iBestValue = 0;
+ for (int iPlayer = 0; iPlayer < MAX_PLAYERS; iPlayer++)
+ {
+ if (iPlayer != getID())
+ {
+ CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iPlayer);
+ if (kLoopPlayer.isAlive() && (kLoopPlayer.getTeam() != getTeam()) && (kLoopPlayer.getNumCities() > 0))
+ {
+ if (GET_TEAM(kLoopPlayer.getTeam()).isOpenBorders(getTeam()))
+ {
+ if (!kLoopPlayer.isNoCorporations() && !kLoopPlayer.isNoForeignCorporations())
+ {
+ int iCitiesCount = 0;
+ int iCitiesHave = 0;
+ int iMultiplier = AI_getAttitudeWeight((PlayerTypes)iPlayer);
+ if (NULL == pArea)
+ {
+ iCitiesCount += 1 + (kLoopPlayer.getNumCities() * 50) / 100;
+ iCitiesHave += std::min(iCitiesCount, kLoopPlayer.getHasCorporationCount(eCorporation));
+ }
+ else
+ {
+ int iPlayerSpreadPercent = (100 * kLoopPlayer.getHasCorporationCount(eCorporation)) / kLoopPlayer.getNumCities();
+ iCitiesCount += pArea->getCitiesPerPlayer((PlayerTypes)iPlayer);
+ iCitiesHave += std::min(iCitiesCount, (iCitiesCount * iPlayerSpreadPercent) / 50);
+ }
+
+ if (iCitiesHave < iCitiesCount)
+ {
+ int iValue = (iMultiplier * iSpreadExternalValue);
+ iValue += ((iMultiplier - 55) * iBonusValue) / 4;
+ iValue /= 100;
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ iBestPlayer = iPlayer;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (iBestValue > iSpreadInternalValue)
+ {
+ if (NULL != peBestPlayer)
+ {
+ *peBestPlayer = (PlayerTypes)iBestPlayer;
+ }
+ return iBestValue;
+ }
+
+ }
+
+ if (NULL != peBestPlayer)
+ {
+ *peBestPlayer = getID();
+ }
+ return iSpreadInternalValue;
+}
+
+//Returns approximately 100 x gpt value of the corporation.
+int CvPlayerAI::AI_corporationValue(CorporationTypes eCorporation, CvCity* pCity) const
+{
+ if (pCity == NULL)
+ {
+ if (getCapitalCity() != NULL)
+ {
+ pCity = getCapitalCity();
+ }
+ }
+ if (NULL == pCity)
+ {
+ return 0;
+ }
+ CvCorporationInfo& kCorp = GC.getCorporationInfo(eCorporation);
+ int iBonusValue = 0;
+
+ for (int iBonus = 0; iBonus < GC.getNumBonusInfos(); iBonus++)
+ {
+ BonusTypes eBonus = (BonusTypes)iBonus;
+ int iBonusCount = pCity->getNumBonuses(eBonus);
+ if (iBonusCount > 0)
+ {
+ for (int i = 0; i < GC.getNUM_CORPORATION_PREREQ_BONUSES(); ++i)
+ {
+ if (eBonus == kCorp.getPrereqBonus(i))
+ {
+ iBonusValue += (100 * kCorp.getYieldProduced(YIELD_FOOD) * iBonusCount);
+ iBonusValue += (100 * kCorp.getYieldProduced(YIELD_PRODUCTION) * iBonusCount);
+ iBonusValue += (60 * kCorp.getYieldProduced(YIELD_COMMERCE) * iBonusCount);
+
+ iBonusValue += (60 * kCorp.getCommerceProduced(COMMERCE_GOLD) * iBonusCount);
+ iBonusValue += (60 * kCorp.getCommerceProduced(COMMERCE_RESEARCH) * iBonusCount);
+ iBonusValue += (25 * kCorp.getCommerceProduced(COMMERCE_CULTURE) * iBonusCount);
+ iBonusValue += (40 * kCorp.getCommerceProduced(COMMERCE_ESPIONAGE) * iBonusCount);
+
+ if (NO_BONUS != kCorp.getBonusProduced())
+ {
+ int iBonuses = getNumAvailableBonuses((BonusTypes)kCorp.getBonusProduced());
+ iBonusValue += (AI_baseBonusVal((BonusTypes)kCorp.getBonusProduced()) * 1000) / (1 + 3 * iBonuses * iBonuses);
+ }
+ }
+ }
+ }
+ }
+ iBonusValue *= 3;
+
+ return iBonusValue;
+}
+
+int CvPlayerAI::AI_areaMissionAIs(CvArea* pArea, MissionAITypes eMissionAI, CvSelectionGroup* pSkipSelectionGroup) const
+{
+ PROFILE_FUNC();
+
+ CvSelectionGroup* pLoopSelectionGroup;
+ CvPlot* pMissionPlot;
+ int iCount;
+ int iLoop;
+
+ iCount = 0;
+
+ for(pLoopSelectionGroup = firstSelectionGroup(&iLoop); pLoopSelectionGroup; pLoopSelectionGroup = nextSelectionGroup(&iLoop))
+ {
+ if (pLoopSelectionGroup != pSkipSelectionGroup)
+ {
+ if (pLoopSelectionGroup->AI_getMissionAIType() == eMissionAI)
+ {
+ pMissionPlot = pLoopSelectionGroup->AI_getMissionAIPlot();
+
+ if (pMissionPlot != NULL)
+ {
+ if (pMissionPlot->area() == pArea)
+ {
+ iCount += pLoopSelectionGroup->getNumUnits();
+ }
+ }
+ }
+ }
+ }
+
+ return iCount;
+}
+
+
+int CvPlayerAI::AI_plotTargetMissionAIs(CvPlot* pPlot, MissionAITypes eMissionAI, CvSelectionGroup* pSkipSelectionGroup, int iRange) const
+{
+ int iClosestTargetRange;
+ return AI_plotTargetMissionAIs(pPlot, &eMissionAI, 1, iClosestTargetRange, pSkipSelectionGroup, iRange);
+}
+
+int CvPlayerAI::AI_plotTargetMissionAIs(CvPlot* pPlot, MissionAITypes eMissionAI, int& iClosestTargetRange, CvSelectionGroup* pSkipSelectionGroup, int iRange) const
+{
+ return AI_plotTargetMissionAIs(pPlot, &eMissionAI, 1, iClosestTargetRange, pSkipSelectionGroup, iRange);
+}
+
+int CvPlayerAI::AI_plotTargetMissionAIs(CvPlot* pPlot, MissionAITypes* aeMissionAI, int iMissionAICount, int& iClosestTargetRange, CvSelectionGroup* pSkipSelectionGroup, int iRange) const
+{
+ PROFILE_FUNC();
+
+ int iCount = 0;
+ iClosestTargetRange = MAX_INT;
+
+ int iLoop;
+ for(CvSelectionGroup* pLoopSelectionGroup = firstSelectionGroup(&iLoop); pLoopSelectionGroup; pLoopSelectionGroup = nextSelectionGroup(&iLoop))
+ {
+ if (pLoopSelectionGroup != pSkipSelectionGroup)
+ {
+ CvPlot* pMissionPlot = pLoopSelectionGroup->AI_getMissionAIPlot();
+
+ if (pMissionPlot != NULL)
+ {
+ MissionAITypes eGroupMissionAI = pLoopSelectionGroup->AI_getMissionAIType();
+ int iDistance = stepDistance(pPlot->getX_INLINE(), pPlot->getY_INLINE(), pMissionPlot->getX_INLINE(), pMissionPlot->getY_INLINE());
+
+ if (iDistance <= iRange)
+ {
+ for (int iMissionAIIndex = 0; iMissionAIIndex < iMissionAICount; iMissionAIIndex++)
+ {
+ if (eGroupMissionAI == aeMissionAI[iMissionAIIndex] || aeMissionAI[iMissionAIIndex] == NO_MISSIONAI)
+ {
+ iCount += pLoopSelectionGroup->getNumUnits();
+
+ if (iDistance < iClosestTargetRange)
+ {
+ iClosestTargetRange = iDistance;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return iCount;
+}
+
+
+int CvPlayerAI::AI_unitTargetMissionAIs(CvUnit* pUnit, MissionAITypes eMissionAI, CvSelectionGroup* pSkipSelectionGroup) const
+{
+ return AI_unitTargetMissionAIs(pUnit, &eMissionAI, 1, pSkipSelectionGroup);
+}
+
+int CvPlayerAI::AI_unitTargetMissionAIs(CvUnit* pUnit, MissionAITypes* aeMissionAI, int iMissionAICount, CvSelectionGroup* pSkipSelectionGroup) const
+{
+ PROFILE_FUNC();
+
+ CvSelectionGroup* pLoopSelectionGroup;
+ int iCount;
+ int iLoop;
+
+ iCount = 0;
+
+ for(pLoopSelectionGroup = firstSelectionGroup(&iLoop); pLoopSelectionGroup; pLoopSelectionGroup = nextSelectionGroup(&iLoop))
+ {
+ if (pLoopSelectionGroup != pSkipSelectionGroup)
+ {
+ if (pLoopSelectionGroup->AI_getMissionAIUnit() == pUnit)
+ {
+ MissionAITypes eGroupMissionAI = pLoopSelectionGroup->AI_getMissionAIType();
+ for (int iMissionAIIndex = 0; iMissionAIIndex < iMissionAICount; iMissionAIIndex++)
+ {
+ if (eGroupMissionAI == aeMissionAI[iMissionAIIndex] || NO_MISSIONAI == aeMissionAI[iMissionAIIndex])
+ {
+ iCount += pLoopSelectionGroup->getNumUnits();
+ }
+ }
+ }
+ }
+ }
+
+ return iCount;
+}
+
+int CvPlayerAI::AI_enemyTargetMissionAIs(MissionAITypes eMissionAI, CvSelectionGroup* pSkipSelectionGroup) const
+{
+ return AI_enemyTargetMissionAIs(&eMissionAI, 1, pSkipSelectionGroup);
+}
+
+int CvPlayerAI::AI_enemyTargetMissionAIs(MissionAITypes* aeMissionAI, int iMissionAICount, CvSelectionGroup* pSkipSelectionGroup) const
+{
+ PROFILE_FUNC();
+
+ int iCount = 0;
+
+ int iLoop;
+ for(CvSelectionGroup* pLoopSelectionGroup = firstSelectionGroup(&iLoop); pLoopSelectionGroup; pLoopSelectionGroup = nextSelectionGroup(&iLoop))
+ {
+ if (pLoopSelectionGroup != pSkipSelectionGroup)
+ {
+ CvPlot* pMissionPlot = pLoopSelectionGroup->AI_getMissionAIPlot();
+
+ if (NULL != pMissionPlot && pMissionPlot->isOwned())
+ {
+ MissionAITypes eGroupMissionAI = pLoopSelectionGroup->AI_getMissionAIType();
+ for (int iMissionAIIndex = 0; iMissionAIIndex < iMissionAICount; iMissionAIIndex++)
+ {
+ if (eGroupMissionAI == aeMissionAI[iMissionAIIndex] || NO_MISSIONAI == aeMissionAI[iMissionAIIndex])
+ {
+ if (GET_TEAM(getTeam()).AI_isChosenWar(pMissionPlot->getTeam()))
+ {
+ iCount += pLoopSelectionGroup->getNumUnits();
+ iCount += pLoopSelectionGroup->getCargo();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return iCount;
+}
+
+int CvPlayerAI::AI_wakePlotTargetMissionAIs(CvPlot* pPlot, MissionAITypes eMissionAI, CvSelectionGroup* pSkipSelectionGroup) const
+{
+ PROFILE_FUNC();
+
+ FAssert(pPlot != NULL);
+
+ int iCount = 0;
+
+ int iLoop;
+ for(CvSelectionGroup* pLoopSelectionGroup = firstSelectionGroup(&iLoop); pLoopSelectionGroup; pLoopSelectionGroup = nextSelectionGroup(&iLoop))
+ {
+ if (pLoopSelectionGroup != pSkipSelectionGroup)
+ {
+ MissionAITypes eGroupMissionAI = pLoopSelectionGroup->AI_getMissionAIType();
+ if (eMissionAI == NO_MISSIONAI || eMissionAI == eGroupMissionAI)
+ {
+ CvPlot* pMissionPlot = pLoopSelectionGroup->AI_getMissionAIPlot();
+ if (pMissionPlot != NULL && pMissionPlot == pPlot)
+ {
+ iCount += pLoopSelectionGroup->getNumUnits();
+ pLoopSelectionGroup->setActivityType(ACTIVITY_AWAKE);
+ }
+ }
+ }
+ }
+
+ return iCount;
+}
+
+CivicTypes CvPlayerAI::AI_bestCivic(CivicOptionTypes eCivicOption) const
+{
+ CivicTypes eBestCivic;
+ int iValue;
+ int iBestValue;
+ int iI;
+
+ iBestValue = MIN_INT;
+ eBestCivic = NO_CIVIC;
+
+ for (iI = 0; iI < GC.getNumCivicInfos(); iI++)
+ {
+ if (GC.getCivicInfo((CivicTypes)iI).getCivicOptionType() == eCivicOption)
+ {
+ if (canDoCivics((CivicTypes)iI))
+ {
+ iValue = AI_civicValue((CivicTypes)iI);
+
+ if (isCivic((CivicTypes)iI))
+ {
+ if (getMaxAnarchyTurns() > 0)
+ {
+ iValue *= 6;
+ iValue /= 5;
+ }
+ else
+ {
+ iValue *= 16;
+ iValue /= 15;
+ }
+ }
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestCivic = ((CivicTypes)iI);
+ }
+ }
+ }
+ }
+
+ return eBestCivic;
+}
+
+
+int CvPlayerAI::AI_civicValue(CivicTypes eCivic) const
+{
+ PROFILE_FUNC();
+
+ bool bWarPlan;
+ int iConnectedForeignCities;
+ int iTotalReligonCount;
+ int iHighestReligionCount;
+ int iWarmongerPercent;
+ int iHappiness;
+ int iValue;
+ int iTempValue;
+ int iI, iJ;
+
+ bool bCultureVictory3 = AI_isDoStrategy(AI_STRATEGY_CULTURE3);
+ bool bCultureVictory2 = AI_isDoStrategy(AI_STRATEGY_CULTURE2);
+
+ FAssertMsg(eCivic < GC.getNumCivicInfos(), "eCivic is expected to be within maximum bounds (invalid Index)");
+ FAssertMsg(eCivic >= 0, "eCivic is expected to be non-negative (invalid Index)");
+
+ CvCivicInfo& kCivic = GC.getCivicInfo(eCivic);
+
+ bWarPlan = (GET_TEAM(getTeam()).getAnyWarPlanCount(true) > 0);
+
+ iConnectedForeignCities = countPotentialForeignTradeCitiesConnected();
+ iTotalReligonCount = countTotalHasReligion();
+ ReligionTypes eBestReligion = AI_bestReligion();
+ if (eBestReligion == NO_RELIGION)
+ {
+ eBestReligion = getStateReligion();
+ }
+ iHighestReligionCount = ((eBestReligion == NO_RELIGION) ? 0 : getHasReligionCount(eBestReligion));
+ iWarmongerPercent = 25000 / std::max(100, (100 + GC.getLeaderHeadInfo(getPersonalityType()).getMaxWarRand()));
+
+ iValue = (getNumCities() * 6);
+
+ iValue += (GC.getCivicInfo(eCivic).getAIWeight() * getNumCities());
+
+ iValue += (getCivicPercentAnger(eCivic) / 10);
+
+ iValue += -(GC.getCivicInfo(eCivic).getAnarchyLength() * getNumCities());
+
+ iValue += -(getSingleCivicUpkeep(eCivic, true));
+
+ iValue += ((kCivic.getGreatPeopleRateModifier() * getNumCities()) / 10);
+ iValue += ((kCivic.getGreatGeneralRateModifier() * getNumMilitaryUnits()) / 50);
+ iValue += ((kCivic.getDomesticGreatGeneralRateModifier() * getNumMilitaryUnits()) / 100);
+ iValue += -((kCivic.getDistanceMaintenanceModifier() * std::max(0, (getNumCities() - 3))) / 8);
+ iValue += -((kCivic.getNumCitiesMaintenanceModifier() * std::max(0, (getNumCities() - 3))) / 8);
+ iValue += (kCivic.getFreeExperience() * getNumCities() * (bWarPlan ? 8 : 5) * iWarmongerPercent) / 100;
+ iValue += ((kCivic.getWorkerSpeedModifier() * AI_getNumAIUnits(UNITAI_WORKER)) / 15);
+ iValue += ((kCivic.getImprovementUpgradeRateModifier() * getNumCities()) / 50);
+ iValue += (kCivic.getMilitaryProductionModifier() * getNumCities() * iWarmongerPercent) / (bWarPlan ? 300 : 500 );
+ iValue += (kCivic.getBaseFreeUnits() / 2);
+ iValue += (kCivic.getBaseFreeMilitaryUnits() / 3);
+ iValue += ((kCivic.getFreeUnitsPopulationPercent() * getTotalPopulation()) / 200);
+ iValue += ((kCivic.getFreeMilitaryUnitsPopulationPercent() * getTotalPopulation()) / 300);
+ iValue += -(kCivic.getGoldPerUnit() * getNumUnits());
+ iValue += -(kCivic.getGoldPerMilitaryUnit() * getNumMilitaryUnits() * iWarmongerPercent) / 200;
+
+ //iValue += ((kCivic.isMilitaryFoodProduction()) ? 0 : 0);
+ iValue += (getWorldSizeMaxConscript(eCivic) * ((bWarPlan) ? (20 + getNumCities()) : ((8 + getNumCities()) / 2)));
+ iValue += ((kCivic.isNoUnhealthyPopulation()) ? (getTotalPopulation() / 3) : 0);
+ if (bWarPlan)
+ {
+ iValue += ((kCivic.getExpInBorderModifier() * getNumMilitaryUnits()) / 200);
+ }
+ iValue += ((kCivic.isBuildingOnlyHealthy()) ? (getNumCities() * 3) : 0);
+ iValue += -((kCivic.getWarWearinessModifier() * getNumCities()) / ((bWarPlan) ? 10 : 50));
+ iValue += (kCivic.getFreeSpecialist() * getNumCities() * 12);
+ iValue += ((kCivic.getTradeRoutes() * std::max(0, iConnectedForeignCities - getNumCities() * 3) * 6) + (getNumCities() * 2));
+ iValue += -((kCivic.isNoForeignTrade()) ? (iConnectedForeignCities * 3) : 0);
+ if (kCivic.isNoCorporations())
+ {
+ iValue -= countHeadquarters() * (40 + 3 * getNumCities());
+ }
+ if (kCivic.isNoForeignCorporations())
+ {
+ for (int iCorp = 0; iCorp < GC.getNumCorporationInfos(); ++iCorp)
+ {
+ if (!GET_TEAM(getTeam()).hasHeadquarters((CorporationTypes)iCorp))
+ {
+ iValue += countCorporations((CorporationTypes)iCorp) * 3;
+ }
+ }
+ }
+ if (kCivic.getCorporationMaintenanceModifier() != 0)
+ {
+ int iCorpCount = 0;
+ int iHQCount = 0;
+ for (int iCorp = 0; iCorp < GC.getNumCorporationInfos(); ++iCorp)
+ {
+ if (GET_TEAM(getTeam()).hasHeadquarters((CorporationTypes)iCorp))
+ {
+ iHQCount++;
+ }
+ iCorpCount += countCorporations((CorporationTypes)iCorp);
+ }
+ iValue += (-kCivic.getCorporationMaintenanceModifier() * (iHQCount * (25 + getNumCities() * 2) + iCorpCount * 7)) / 25;
+
+ }
+
+ if (kCivic.getCivicPercentAnger() != 0)
+ {
+ int iNumOtherCities = GC.getGameINLINE().getNumCities() - getNumCities();
+ iValue += (30 * getNumCities() * getCivicPercentAnger(eCivic, true)) / kCivic.getCivicPercentAnger();
+
+ int iTargetGameTurn = 2 * getNumCities() * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGrowthPercent();
+ iTargetGameTurn /= GC.getGame().countCivPlayersEverAlive();
+ iTargetGameTurn += GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGrowthPercent() * 30;
+
+ iTargetGameTurn /= 100;
+ iTargetGameTurn = std::max(10, iTargetGameTurn);
+
+ int iElapsedTurns = GC.getGame().getElapsedGameTurns();
+
+ if (iElapsedTurns > iTargetGameTurn)
+ {
+ iValue += (std::min(iTargetGameTurn, iElapsedTurns - iTargetGameTurn) * (iNumOtherCities * kCivic.getCivicPercentAnger())) / (15 * iTargetGameTurn);
+ }
+ }
+
+ if (kCivic.getExtraHealth() != 0)
+ {
+ iValue += (getNumCities() * 6 * AI_getHealthWeight(isCivic(eCivic) ? -kCivic.getExtraHealth() : kCivic.getExtraHealth(), 1)) / 100;
+ }
+
+ iTempValue = kCivic.getHappyPerMilitaryUnit() * 3;
+ if (iTempValue != 0)
+ {
+ iValue += (getNumCities() * 9 * AI_getHappinessWeight(isCivic(eCivic) ? -iTempValue : iTempValue, 1)) / 100;
+ }
+
+ iTempValue = kCivic.getLargestCityHappiness();
+ if (iTempValue != 0)
+ {
+ iValue += (12 * std::min(getNumCities(), GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getTargetNumCities()) * AI_getHappinessWeight(isCivic(eCivic) ? -iTempValue : iTempValue, 1)) / 100;
+ }
+
+ if (kCivic.getWarWearinessModifier() != 0)
+ {
+ int iAngerPercent = getWarWearinessPercentAnger();
+ int iPopulation = 3 + (getTotalPopulation() / std::max(1, getNumCities()));
+
+ int iTempValue = (-kCivic.getWarWearinessModifier() * iAngerPercent * iPopulation) / (GC.getPERCENT_ANGER_DIVISOR() * 100);
+ if (iTempValue != 0)
+ {
+ iValue += (11 * getNumCities() * AI_getHappinessWeight(isCivic(eCivic) ? -iTempValue : iTempValue, 1)) / 100;
+ }
+ }
+
+ iValue += (kCivic.getNonStateReligionHappiness() * (iTotalReligonCount - iHighestReligionCount) * 5);
+
+ if (kCivic.isStateReligion())
+ {
+ if (iHighestReligionCount > 0)
+ {
+ iValue += iHighestReligionCount;
+
+ iValue += ((kCivic.isNoNonStateReligionSpread()) ? ((getNumCities() - iHighestReligionCount) * 2) : 0);
+ iValue += (kCivic.getStateReligionHappiness() * iHighestReligionCount * 4);
+ iValue += ((kCivic.getStateReligionGreatPeopleRateModifier() * iHighestReligionCount) / 20);
+ iValue += (kCivic.getStateReligionGreatPeopleRateModifier() / 4);
+ iValue += ((kCivic.getStateReligionUnitProductionModifier() * iHighestReligionCount) / 4);
+ iValue += ((kCivic.getStateReligionBuildingProductionModifier() * iHighestReligionCount) / 3);
+ iValue += (kCivic.getStateReligionFreeExperience() * iHighestReligionCount * ((bWarPlan) ? 6 : 2));
+ }
+ }
+
+ for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
+ {
+ iTempValue = 0;
+
+ iTempValue += ((kCivic.getYieldModifier(iI) * getNumCities()) / 2);
+ iTempValue += ((kCivic.getCapitalYieldModifier(iI) * 3) / 4);
+ CvCity* pCapital = getCapitalCity();
+ if (pCapital)
+ {
+ iTempValue += ((kCivic.getCapitalYieldModifier(iI) * pCapital->getBaseYieldRate((YieldTypes)iI)) / 80);
+ }
+ iTempValue += ((kCivic.getTradeYieldModifier(iI) * getNumCities()) / 11);
+
+ for (iJ = 0; iJ < GC.getNumImprovementInfos(); iJ++)
+ {
+ iTempValue += (AI_averageYieldMultiplier((YieldTypes)iI) * (kCivic.getImprovementYieldChanges(iJ, iI) * (getImprovementCount((ImprovementTypes)iJ) + getNumCities() * 2))) / 100;
+ }
+
+ if (iI == YIELD_FOOD)
+ {
+ iTempValue *= 3;
+ }
+ else if (iI == YIELD_PRODUCTION)
+ {
+ iTempValue *= ((AI_avoidScience()) ? 6 : 2);
+ }
+ else if (iI == YIELD_COMMERCE)
+ {
+ iTempValue *= ((AI_avoidScience()) ? 1 : 2);
+ }
+
+ iValue += iTempValue;
+ }
+
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
+ {
+ iTempValue = 0;
+
+ iTempValue += ((kCivic.getCommerceModifier(iI) * getNumCities()) / 3);
+ iTempValue += (kCivic.getCapitalCommerceModifier(iI) / 2);
+ if (iI == COMMERCE_ESPIONAGE)
+ {
+ iTempValue *= AI_getEspionageWeight();
+ iTempValue /= 500;
+ }
+ iTempValue += ((kCivic.getSpecialistExtraCommerce(iI) * getTotalPopulation()) / 15);
+
+ iTempValue *= AI_commerceWeight((CommerceTypes)iI);
+
+ if ((iI == COMMERCE_CULTURE) && bCultureVictory2)
+ {
+ iTempValue *= 2;
+ if (bCultureVictory3)
+ {
+ iTempValue *= 2;
+ }
+ }
+ iTempValue /= 100;
+
+ iValue += iTempValue;
+ }
+
+ for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
+ {
+ if (kCivic.getBuildingHappinessChanges(iI) != 0)
+ {
+ iValue += (kCivic.getBuildingHappinessChanges(iI) * getBuildingClassCount((BuildingClassTypes)iI) * 3);
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumFeatureInfos(); iI++)
+ {
+ iHappiness = kCivic.getFeatureHappinessChanges(iI);
+
+ if (iHappiness != 0)
+ {
+ iValue += (iHappiness * countCityFeatures((FeatureTypes)iI) * 5);
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumHurryInfos(); iI++)
+ {
+ if (kCivic.isHurry(iI))
+ {
+ iTempValue = 0;
+
+ if (GC.getHurryInfo((HurryTypes)iI).getGoldPerProduction() > 0)
+ {
+ iTempValue += ((((AI_avoidScience()) ? 50 : 25) * getNumCities()) / GC.getHurryInfo((HurryTypes)iI).getGoldPerProduction());
+ }
+ iTempValue += (GC.getHurryInfo((HurryTypes)iI).getProductionPerPopulation() * getNumCities() * (bWarPlan ? 2 : 1)) / 5;
+ iValue += iTempValue;
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumSpecialBuildingInfos(); iI++)
+ {
+ if (kCivic.isSpecialBuildingNotRequired(iI))
+ {
+ iValue += ((getNumCities() / 2) + 1); // XXX
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
+ {
+ iTempValue = 0;
+ if (kCivic.isSpecialistValid(iI))
+ {
+ iTempValue += ((getNumCities() * (bCultureVictory3 ? 10 : 1)) + 6);
+ }
+ iValue += (iTempValue / 2);
+ }
+
+ if (GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivic() == eCivic)
+ {
+ if (!kCivic.isStateReligion() || iHighestReligionCount > 0)
+ {
+ iValue *= 5;
+ iValue /= 4;
+ iValue += 6 * getNumCities();
+ iValue += 20;
+ }
+ }
+
+ if (AI_isDoStrategy(AI_STRATEGY_CULTURE2) && (GC.getCivicInfo(eCivic).isNoNonStateReligionSpread()))
+ {
+ iValue /= 10;
+ }
+
+ return iValue;
+}
+
+
+ReligionTypes CvPlayerAI::AI_bestReligion() const
+{
+ ReligionTypes eBestReligion;
+ int iValue;
+ int iBestValue;
+ int iI;
+
+ iBestValue = 0;
+ eBestReligion = NO_RELIGION;
+
+ ReligionTypes eFavorite = (ReligionTypes)GC.getLeaderHeadInfo(getLeaderType()).getFavoriteReligion();
+
+ for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
+ {
+ if (canDoReligion((ReligionTypes)iI))
+ {
+ iValue = AI_religionValue((ReligionTypes)iI);
+
+ if (getStateReligion() == ((ReligionTypes)iI))
+ {
+ iValue *= 4;
+ iValue /= 3;
+ }
+
+ if (eFavorite == iI)
+ {
+ iValue *= 5;
+ iValue /= 4;
+ }
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestReligion = ((ReligionTypes)iI);
+ }
+ }
+ }
+
+ if ((NO_RELIGION == eBestReligion) || AI_isDoStrategy(AI_STRATEGY_MISSIONARY))
+ {
+ return eBestReligion;
+ }
+
+ int iBestCount = getHasReligionCount(eBestReligion);
+ int iSpreadPercent = (iBestCount * 100) / std::max(1, getNumCities());
+ int iPurityPercent = (iBestCount * 100) / std::max(1, countTotalHasReligion());
+ if (iPurityPercent < 49)
+ {
+ if (iSpreadPercent > ((eBestReligion == eFavorite) ? 65 : 75))
+ {
+ if (iPurityPercent > ((eBestReligion == eFavorite) ? 25 : 32))
+ {
+ return eBestReligion;
+ }
+ }
+ return NO_RELIGION;
+ }
+
+ return eBestReligion;
+}
+
+
+int CvPlayerAI::AI_religionValue(ReligionTypes eReligion) const
+{
+ if (getHasReligionCount(eReligion) == 0)
+ {
+ return 0;
+ }
+
+ int iValue = GC.getGameINLINE().countReligionLevels(eReligion);
+
+ int iLoop;
+ CvCity* pLoopCity;
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ if (pLoopCity->isHasReligion(eReligion))
+ {
+ iValue += pLoopCity->getPopulation();
+ }
+ }
+
+ CvCity* pHolyCity = GC.getGameINLINE().getHolyCity(eReligion);
+ if (pHolyCity != NULL)
+ {
+ bool bOurHolyCity = pHolyCity->getOwnerINLINE() == getID();
+ bool bOurTeamHolyCity = pHolyCity->getTeam() == getTeam();
+
+ if (bOurHolyCity || bOurTeamHolyCity)
+ {
+ int iCommerceCount = 0;
+
+ for (int iI = 0; iI < GC.getNumBuildingInfos(); iI++)
+ {
+ if (pHolyCity->getNumActiveBuilding((BuildingTypes)iI) > 0)
+ {
+ for (int iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
+ {
+ if (GC.getBuildingInfo((BuildingTypes)iI).getGlobalReligionCommerce() == eReligion)
+ {
+ iCommerceCount += GC.getReligionInfo(eReligion).getGlobalReligionCommerce((CommerceTypes)iJ) * pHolyCity->getNumActiveBuilding((BuildingTypes)iI);
+ }
+ }
+ }
+ }
+
+ if (bOurHolyCity)
+ {
+ iValue *= (3 + iCommerceCount);
+ iValue /= 2;
+ }
+ else if (bOurTeamHolyCity)
+ {
+ iValue *= (4 + iCommerceCount);
+ iValue /= 3;
+ }
+ }
+ }
+
+ return iValue;
+}
+
+EspionageMissionTypes CvPlayerAI::AI_bestPlotEspionage(CvPlot* pSpyPlot, PlayerTypes& eTargetPlayer, CvPlot*& pPlot, int& iData) const
+{
+ //ooookay what missions are possible
+
+ FAssert(pSpyPlot != NULL);
+
+ pPlot = NULL;
+ iData = -1;
+
+ EspionageMissionTypes eBestMission = NO_ESPIONAGEMISSION;
+ int iBestValue = 0;
+
+ if (pSpyPlot->isOwned())
+ {
+ if (pSpyPlot->getTeam() != getTeam())
+ {
+ if (!AI_isDoStrategy(AI_STRATEGY_BIG_ESPIONAGE) && (GET_TEAM(getTeam()).AI_getWarPlan(pSpyPlot->getTeam()) != NO_WARPLAN || AI_getAttitudeWeight(pSpyPlot->getOwner()) < (GC.getGameINLINE().isOption(GAMEOPTION_AGGRESSIVE_AI) ? 50 : 1)))
+ {
+ //Destroy Improvement.
+ if (pSpyPlot->getImprovementType() != NO_IMPROVEMENT)
+ {
+ for (int iMission = 0; iMission < GC.getNumEspionageMissionInfos(); ++iMission)
+ {
+ CvEspionageMissionInfo& kMissionInfo = GC.getEspionageMissionInfo((EspionageMissionTypes)iMission);
+
+ if (kMissionInfo.isDestroyImprovement())
+ {
+ int iValue = AI_espionageVal(pSpyPlot->getOwnerINLINE(), (EspionageMissionTypes)iMission, pSpyPlot, -1);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestMission = (EspionageMissionTypes)iMission;
+ eTargetPlayer = pSpyPlot->getOwnerINLINE();
+ pPlot = pSpyPlot;
+ iData = -1;
+ }
+ }
+ }
+ }
+ }
+
+ CvCity* pCity = pSpyPlot->getPlotCity();
+ if (pCity != NULL)
+ {
+ //Something malicious
+ if (AI_getAttitudeWeight(pSpyPlot->getOwner()) < (GC.getGameINLINE().isOption(GAMEOPTION_AGGRESSIVE_AI) ? 50 : 1))
+ {
+ //Destroy Building.
+ if (!AI_isDoStrategy(AI_STRATEGY_BIG_ESPIONAGE))
+ {
+ for (int iMission = 0; iMission < GC.getNumEspionageMissionInfos(); ++iMission)
+ {
+ CvEspionageMissionInfo& kMissionInfo = GC.getEspionageMissionInfo((EspionageMissionTypes)iMission);
+ if (kMissionInfo.getDestroyBuildingCostFactor() > 0)
+ {
+ for (int iBuilding = 0; iBuilding < GC.getNumBuildingInfos(); iBuilding++)
+ {
+ BuildingTypes eBuilding = (BuildingTypes)iBuilding;
+
+ if (pCity->getNumBuilding(eBuilding) > 0)
+ {
+ int iValue = AI_espionageVal(pSpyPlot->getOwnerINLINE(), (EspionageMissionTypes)iMission, pSpyPlot, iBuilding);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestMission = (EspionageMissionTypes)iMission;
+ eTargetPlayer = pSpyPlot->getOwnerINLINE();
+ pPlot = pSpyPlot;
+ iData = iBuilding;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //Destroy Project
+ for (int iMission = 0; iMission < GC.getNumEspionageMissionInfos(); ++iMission)
+ {
+ CvEspionageMissionInfo& kMissionInfo = GC.getEspionageMissionInfo((EspionageMissionTypes)iMission);
+ if (kMissionInfo.getDestroyProjectCostFactor() > 0)
+ {
+ for (int iProject = 0; iProject < GC.getNumProjectInfos(); iProject++)
+ {
+ ProjectTypes eProject = (ProjectTypes)iProject;
+
+ int iValue = AI_espionageVal(pSpyPlot->getOwnerINLINE(), (EspionageMissionTypes)iMission, pSpyPlot, iProject);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestMission = (EspionageMissionTypes)iMission;
+ eTargetPlayer = pSpyPlot->getOwnerINLINE();
+ pPlot = pSpyPlot;
+ iData = iProject;
+ }
+ }
+ }
+ }
+
+ //General dataless city mission.
+ if (!AI_isDoStrategy(AI_STRATEGY_BIG_ESPIONAGE))
+ {
+ for (int iMission = 0; iMission < GC.getNumEspionageMissionInfos(); ++iMission)
+ {
+ CvEspionageMissionInfo& kMissionInfo = GC.getEspionageMissionInfo((EspionageMissionTypes)iMission);
+ {
+ if ((kMissionInfo.getCityPoisonWaterCounter() > 0) || (kMissionInfo.getDestroyProductionCostFactor() > 0)
+ || (kMissionInfo.getStealTreasuryTypes() > 0))
+ {
+ int iValue = AI_espionageVal(pSpyPlot->getOwnerINLINE(), (EspionageMissionTypes)iMission, pSpyPlot, -1);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestMission = (EspionageMissionTypes)iMission;
+ eTargetPlayer = pSpyPlot->getOwnerINLINE();
+ pPlot = pSpyPlot;
+ iData = -1;
+ }
+ }
+ }
+ }
+ }
+
+ //Disruption suitable for war.
+ if (GET_TEAM(getTeam()).isAtWar(pSpyPlot->getTeam()))
+ {
+ for (int iMission = 0; iMission < GC.getNumEspionageMissionInfos(); ++iMission)
+ {
+ CvEspionageMissionInfo& kMissionInfo = GC.getEspionageMissionInfo((EspionageMissionTypes)iMission);
+ if ((kMissionInfo.getCityRevoltCounter() > 0) || (kMissionInfo.getPlayerAnarchyCounter() > 0))
+ {
+ int iValue = AI_espionageVal(pSpyPlot->getOwnerINLINE(), (EspionageMissionTypes)iMission, pSpyPlot, -1);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestMission = (EspionageMissionTypes)iMission;
+ eTargetPlayer = pSpyPlot->getOwnerINLINE();
+ pPlot = pSpyPlot;
+ iData = -1;
+ }
+ }
+ }
+ }
+ }
+
+ //Steal Technology
+ for (int iMission = 0; iMission < GC.getNumEspionageMissionInfos(); ++iMission)
+ {
+ CvEspionageMissionInfo& kMissionInfo = GC.getEspionageMissionInfo((EspionageMissionTypes)iMission);
+ if (kMissionInfo.getBuyTechCostFactor() > 0)
+ {
+ for (int iTech = 0; iTech < GC.getNumTechInfos(); iTech++)
+ {
+ TechTypes eTech = (TechTypes)iTech;
+ int iValue = AI_espionageVal(pSpyPlot->getOwnerINLINE(), (EspionageMissionTypes)iMission, pSpyPlot, eTech);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestMission = (EspionageMissionTypes)iMission;
+ eTargetPlayer = pSpyPlot->getOwnerINLINE();
+ pPlot = pSpyPlot;
+ iData = eTech;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return eBestMission;
+}
+
+int CvPlayerAI::AI_espionageVal(PlayerTypes eTargetPlayer, EspionageMissionTypes eMission, CvPlot* pPlot, int iData) const
+{
+ TeamTypes eTargetTeam = GET_PLAYER(eTargetPlayer).getTeam();
+
+ if (eTargetPlayer == NO_PLAYER)
+ {
+ return 0;
+ }
+
+ int iCost = getEspionageMissionCost(eMission, eTargetPlayer, pPlot, iData);
+
+ if (!canDoEspionageMission(eMission, eTargetPlayer, pPlot, iData, NULL))
+ {
+ return 0;
+ }
+
+// if (GET_TEAM(getTeam()).getEspionagePointsAgainstTeam(eTargetTeam) - iCost < GET_TEAM(GET_PLAYER(eTargetPlayer).getTeam()).getEspionagePointsAgainstTeam(getTeam()))
+// {
+// return 0;
+// }
+
+ int iValue = 0;
+ if (GC.getEspionageMissionInfo(eMission).isDestroyImprovement())
+ {
+ if (NULL != pPlot)
+ {
+ if (pPlot->getOwnerINLINE() == eTargetPlayer)
+ {
+ ImprovementTypes eImprovement = pPlot->getImprovementType();
+ if (eImprovement != NO_IMPROVEMENT)
+ {
+ BonusTypes eBonus = pPlot->getNonObsoleteBonusType(GET_PLAYER(eTargetPlayer).getTeam());
+ if (NO_BONUS != eBonus)
+ {
+ iValue += GET_PLAYER(eTargetPlayer).AI_bonusVal(eBonus, -1);
+ }
+ else
+ {
+ int iTempValue = 0;
+ if (NULL != pPlot->getWorkingCity())
+ {
+ iTempValue += (pPlot->calculateImprovementYieldChange(eImprovement, YIELD_FOOD, pPlot->getOwnerINLINE()) * 2);
+ iTempValue += (pPlot->calculateImprovementYieldChange(eImprovement, YIELD_PRODUCTION, pPlot->getOwnerINLINE()) * 1);
+ iTempValue += (pPlot->calculateImprovementYieldChange(eImprovement, YIELD_COMMERCE, pPlot->getOwnerINLINE()) * 4);
+ iTempValue += GC.getImprovementInfo(eImprovement).getUpgradeTime() / 2;
+ iValue += iTempValue;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (GC.getEspionageMissionInfo(eMission).getDestroyBuildingCostFactor() > 0)
+ {
+ if (canSpyDestroyBuilding(eTargetPlayer, (BuildingTypes)iData))
+ {
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+
+ if (NULL != pCity)
+ {
+ if (pCity->getNumRealBuilding((BuildingTypes)iData) > 0)
+ {
+ CvBuildingInfo& kBuilding = GC.getBuildingInfo((BuildingTypes)iData);
+ if ((kBuilding.getProductionCost() > 1) && !isWorldWonderClass((BuildingClassTypes)kBuilding.getBuildingClassType()))
+ {
+ iValue += pCity->AI_buildingValue((BuildingTypes)iData);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (GC.getEspionageMissionInfo(eMission).getDestroyProjectCostFactor() > 0)
+ {
+ if (canSpyDestroyProject(eTargetPlayer, (ProjectTypes)iData))
+ {
+ CvProjectInfo& kProject = GC.getProjectInfo((ProjectTypes)iData);
+
+ iValue += getProductionNeeded((ProjectTypes)iData) * ((kProject.getMaxTeamInstances() == 1) ? 3 : 2);
+ }
+ }
+
+ if (GC.getEspionageMissionInfo(eMission).getDestroyProductionCostFactor() > 0)
+ {
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+ FAssert(pCity != NULL);
+ if (pCity != NULL)
+ {
+ int iTempValue = pCity->getProduction();
+ if (iTempValue > 0)
+ {
+ if (pCity->getProductionProject() != NO_PROJECT)
+ {
+ CvProjectInfo& kProject = GC.getProjectInfo(pCity->getProductionProject());
+ iValue += iTempValue * ((kProject.getMaxTeamInstances() == 1) ? 4 : 2);
+ }
+ else if (pCity->getProductionBuilding() != NO_BUILDING)
+ {
+ CvBuildingInfo& kBuilding = GC.getBuildingInfo(pCity->getProductionBuilding());
+ if (isWorldWonderClass((BuildingClassTypes)kBuilding.getBuildingClassType()))
+ {
+ iValue += 3 * iTempValue;
+ }
+ iValue += iTempValue;
+ }
+ else
+ {
+ iValue += iTempValue;
+ }
+ }
+ }
+ }
+ }
+
+
+ if (GC.getEspionageMissionInfo(eMission).getDestroyUnitCostFactor() > 0 || GC.getEspionageMissionInfo(eMission).getBuyUnitCostFactor() > 0)
+ {
+ if (NULL != pPlot)
+ {
+ CvUnit* pUnit = GET_PLAYER(eTargetPlayer).getUnit(iData);
+
+ if (NULL != pUnit)
+ {
+ UnitTypes eUnit = pUnit->getUnitType();
+
+ iValue += GET_PLAYER(eTargetPlayer).AI_unitValue(eUnit, (UnitAITypes)GC.getUnitInfo(eUnit).getDefaultUnitAIType(), pUnit->area());
+
+ if (GC.getEspionageMissionInfo(eMission).getBuyUnitCostFactor() > 0)
+ {
+ if (!canTrain(eUnit) || getProductionNeeded(eUnit) > iCost)
+ {
+ iValue += AI_unitValue(eUnit, (UnitAITypes)GC.getUnitInfo(eUnit).getDefaultUnitAIType(), pUnit->area());;
+ }
+ }
+ }
+ }
+ }
+
+ if (GC.getEspionageMissionInfo(eMission).getStealTreasuryTypes() > 0)
+ {
+ int iGoldStolen = iData;
+ return 2 * (2 * iGoldStolen - iCost);
+ }
+
+ if (GC.getEspionageMissionInfo(eMission).getCounterespionageNumTurns() > 0)
+ {
+ //iValue += 100 * GET_TEAM(getTeam()).AI_getAttitudeVal(GET_PLAYER(eTargetPlayer).getTeam());
+ }
+
+ if (GC.getEspionageMissionInfo(eMission).getBuyCityCostFactor() > 0)
+ {
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+
+ if (NULL != pCity)
+ {
+ iValue += AI_cityTradeVal(pCity);
+ }
+ }
+ }
+
+ if (GC.getEspionageMissionInfo(eMission).getCityInsertCultureAmountFactor() > 0)
+ {
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+ if (NULL != pCity)
+ {
+ if (pCity->getOwner() != getID())
+ {
+ int iCultureAmount = GC.getEspionageMissionInfo(eMission).getCityInsertCultureAmountFactor() * pPlot->getCulture(getID());
+ iCultureAmount /= 100;
+ if (pCity->calculateCulturePercent(getID()) > 40)
+ {
+ iValue += iCultureAmount * 3;
+ }
+ }
+ }
+ }
+ }
+
+ if (GC.getEspionageMissionInfo(eMission).getCityPoisonWaterCounter() > 0)
+ {
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+
+ if (NULL != pCity)
+ {
+ int iCityHealth = pCity->goodHealth() - pCity->badHealth(false, 0);
+ int iBaseUnhealth = GC.getEspionageMissionInfo(eMission).getCityPoisonWaterCounter();
+
+ int iAverageUnhealth = std::max(0, iBaseUnhealth - iCityHealth);
+ iAverageUnhealth += std::max(0, (iBaseUnhealth / 2) - iCityHealth);
+
+ iAverageUnhealth /= 2;
+
+ iValue += 8 * iAverageUnhealth * iBaseUnhealth;
+ }
+ }
+ }
+
+ if (GC.getEspionageMissionInfo(eMission).getCityUnhappinessCounter() > 0)
+ {
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+
+ if (NULL != pCity)
+ {
+ int iCityUnhappy = pCity->unhappyLevel();
+ if (iCityUnhappy > 0)
+ {
+ int iBaseAnger = GC.getEspionageMissionInfo(eMission).getCityUnhappinessCounter();
+
+ iValue += 7 * iBaseAnger * iBaseAnger;
+ }
+ }
+ }
+ }
+
+ if (GC.getEspionageMissionInfo(eMission).getCityRevoltCounter() > 0)
+ {
+ if (NULL != pPlot)
+ {
+ CvCity* pCity = pPlot->getPlotCity();
+
+ if (NULL != pCity)
+ {
+ if (atWar(getTeam(), pCity->getTeam()))
+ {
+ iValue -= 10;
+ iValue += 5 * AI_adjacentPotentialAttackers(pPlot, true);
+ }
+ }
+ }
+ }
+
+ if (GC.getEspionageMissionInfo(eMission).getBuyTechCostFactor() > 0)
+ {
+ if (iCost < GET_TEAM(getTeam()).getResearchLeft((TechTypes)iData) * 4 / 3)
+ {
+ iValue += GET_TEAM(getTeam()).AI_techTradeVal((TechTypes)iData, GET_PLAYER(eTargetPlayer).getTeam());
+ }
+ }
+
+ if (GC.getEspionageMissionInfo(eMission).getSwitchCivicCostFactor() > 0)
+ {
+ iValue += AI_civicTradeVal((CivicTypes)iData, eTargetPlayer);
+ }
+
+ if (GC.getEspionageMissionInfo(eMission).getSwitchReligionCostFactor() > 0)
+ {
+ iValue += AI_religionTradeVal((ReligionTypes)iData, eTargetPlayer);
+ }
+
+ if (GC.getEspionageMissionInfo(eMission).getPlayerAnarchyCounter() > 0)
+ {
+ // AI doesn't use Player Anarchy
+ }
+
+ return iValue;
+
+}
+
+int CvPlayerAI::AI_getPeaceWeight() const
+{
+ return m_iPeaceWeight;
+}
+
+
+void CvPlayerAI::AI_setPeaceWeight(int iNewValue)
+{
+ m_iPeaceWeight = iNewValue;
+}
+
+int CvPlayerAI::AI_getEspionageWeight() const
+{
+ if (GC.getGameINLINE().isOption(GAMEOPTION_NO_ESPIONAGE))
+ {
+ return 0;
+ }
+ return m_iEspionageWeight;
+}
+
+void CvPlayerAI::AI_setEspionageWeight(int iNewValue)
+{
+ m_iEspionageWeight = iNewValue;
+}
+
+
+int CvPlayerAI::AI_getAttackOddsChange() const
+{
+ return m_iAttackOddsChange;
+}
+
+
+void CvPlayerAI::AI_setAttackOddsChange(int iNewValue)
+{
+ m_iAttackOddsChange = iNewValue;
+}
+
+
+int CvPlayerAI::AI_getCivicTimer() const
+{
+ return m_iCivicTimer;
+}
+
+
+void CvPlayerAI::AI_setCivicTimer(int iNewValue)
+{
+ m_iCivicTimer = iNewValue;
+ FAssert(AI_getCivicTimer() >= 0);
+}
+
+
+void CvPlayerAI::AI_changeCivicTimer(int iChange)
+{
+ AI_setCivicTimer(AI_getCivicTimer() + iChange);
+}
+
+
+int CvPlayerAI::AI_getReligionTimer() const
+{
+ return m_iReligionTimer;
+}
+
+
+void CvPlayerAI::AI_setReligionTimer(int iNewValue)
+{
+ m_iReligionTimer = iNewValue;
+ FAssert(AI_getReligionTimer() >= 0);
+}
+
+
+void CvPlayerAI::AI_changeReligionTimer(int iChange)
+{
+ AI_setReligionTimer(AI_getReligionTimer() + iChange);
+}
+
+int CvPlayerAI::AI_getExtraGoldTarget() const
+{
+ return m_iExtraGoldTarget;
+}
+
+void CvPlayerAI::AI_setExtraGoldTarget(int iNewValue)
+{
+ m_iExtraGoldTarget = iNewValue;
+}
+
+int CvPlayerAI::AI_getNumTrainAIUnits(UnitAITypes eIndex) const
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < NUM_UNITAI_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
+ return m_aiNumTrainAIUnits[eIndex];
+}
+
+
+void CvPlayerAI::AI_changeNumTrainAIUnits(UnitAITypes eIndex, int iChange)
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < NUM_UNITAI_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
+ m_aiNumTrainAIUnits[eIndex] = (m_aiNumTrainAIUnits[eIndex] + iChange);
+ FAssert(AI_getNumTrainAIUnits(eIndex) >= 0);
+}
+
+
+int CvPlayerAI::AI_getNumAIUnits(UnitAITypes eIndex) const
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < NUM_UNITAI_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
+ return m_aiNumAIUnits[eIndex];
+}
+
+
+void CvPlayerAI::AI_changeNumAIUnits(UnitAITypes eIndex, int iChange)
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < NUM_UNITAI_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
+ m_aiNumAIUnits[eIndex] = (m_aiNumAIUnits[eIndex] + iChange);
+ FAssert(AI_getNumAIUnits(eIndex) >= 0);
+}
+
+
+int CvPlayerAI::AI_getSameReligionCounter(PlayerTypes eIndex) const
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ return m_aiSameReligionCounter[eIndex];
+}
+
+
+void CvPlayerAI::AI_changeSameReligionCounter(PlayerTypes eIndex, int iChange)
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ m_aiSameReligionCounter[eIndex] = (m_aiSameReligionCounter[eIndex] + iChange);
+ FAssert(AI_getSameReligionCounter(eIndex) >= 0);
+}
+
+
+int CvPlayerAI::AI_getDifferentReligionCounter(PlayerTypes eIndex) const
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ return m_aiDifferentReligionCounter[eIndex];
+}
+
+
+void CvPlayerAI::AI_changeDifferentReligionCounter(PlayerTypes eIndex, int iChange)
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ m_aiDifferentReligionCounter[eIndex] = (m_aiDifferentReligionCounter[eIndex] + iChange);
+ FAssert(AI_getDifferentReligionCounter(eIndex) >= 0);
+}
+
+
+int CvPlayerAI::AI_getFavoriteCivicCounter(PlayerTypes eIndex) const
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ return m_aiFavoriteCivicCounter[eIndex];
+}
+
+
+void CvPlayerAI::AI_changeFavoriteCivicCounter(PlayerTypes eIndex, int iChange)
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ m_aiFavoriteCivicCounter[eIndex] = (m_aiFavoriteCivicCounter[eIndex] + iChange);
+ FAssert(AI_getFavoriteCivicCounter(eIndex) >= 0);
+}
+
+
+int CvPlayerAI::AI_getBonusTradeCounter(PlayerTypes eIndex) const
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ return m_aiBonusTradeCounter[eIndex];
+}
+
+
+void CvPlayerAI::AI_changeBonusTradeCounter(PlayerTypes eIndex, int iChange)
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ m_aiBonusTradeCounter[eIndex] = (m_aiBonusTradeCounter[eIndex] + iChange);
+ FAssert(AI_getBonusTradeCounter(eIndex) >= 0);
+}
+
+
+int CvPlayerAI::AI_getPeacetimeTradeValue(PlayerTypes eIndex) const
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ return m_aiPeacetimeTradeValue[eIndex];
+}
+
+
+void CvPlayerAI::AI_changePeacetimeTradeValue(PlayerTypes eIndex, int iChange)
+{
+ PROFILE_FUNC();
+
+ int iI;
+
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+
+ if (iChange != 0)
+ {
+ m_aiPeacetimeTradeValue[eIndex] = (m_aiPeacetimeTradeValue[eIndex] + iChange);
+ FAssert(AI_getPeacetimeTradeValue(eIndex) >= 0);
+
+ FAssert(iChange > 0);
+
+ if (iChange > 0)
+ {
+ if (GET_PLAYER(eIndex).getTeam() != getTeam())
+ {
+ for (iI = 0; iI < MAX_CIV_TEAMS; iI++)
+ {
+ if (GET_TEAM((TeamTypes)iI).isAlive())
+ {
+ if (GET_TEAM((TeamTypes)iI).AI_getWorstEnemy() == getTeam())
+ {
+ GET_TEAM((TeamTypes)iI).AI_changeEnemyPeacetimeTradeValue(GET_PLAYER(eIndex).getTeam(), iChange);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+int CvPlayerAI::AI_getPeacetimeGrantValue(PlayerTypes eIndex) const
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ return m_aiPeacetimeGrantValue[eIndex];
+}
+
+
+void CvPlayerAI::AI_changePeacetimeGrantValue(PlayerTypes eIndex, int iChange)
+{
+ PROFILE_FUNC();
+
+ int iI;
+
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+
+ if (iChange != 0)
+ {
+ m_aiPeacetimeGrantValue[eIndex] = (m_aiPeacetimeGrantValue[eIndex] + iChange);
+ FAssert(AI_getPeacetimeGrantValue(eIndex) >= 0);
+
+ FAssert(iChange > 0);
+
+ if (iChange > 0)
+ {
+ if (GET_PLAYER(eIndex).getTeam() != getTeam())
+ {
+ for (iI = 0; iI < MAX_CIV_TEAMS; iI++)
+ {
+ if (GET_TEAM((TeamTypes)iI).isAlive())
+ {
+ if (GET_TEAM((TeamTypes)iI).AI_getWorstEnemy() == getTeam())
+ {
+ GET_TEAM((TeamTypes)iI).AI_changeEnemyPeacetimeGrantValue(GET_PLAYER(eIndex).getTeam(), iChange);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+int CvPlayerAI::AI_getGoldTradedTo(PlayerTypes eIndex) const
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ return m_aiGoldTradedTo[eIndex];
+}
+
+
+void CvPlayerAI::AI_changeGoldTradedTo(PlayerTypes eIndex, int iChange)
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ m_aiGoldTradedTo[eIndex] = (m_aiGoldTradedTo[eIndex] + iChange);
+ FAssert(AI_getGoldTradedTo(eIndex) >= 0);
+}
+
+
+int CvPlayerAI::AI_getAttitudeExtra(PlayerTypes eIndex) const
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ return m_aiAttitudeExtra[eIndex];
+}
+
+
+void CvPlayerAI::AI_setAttitudeExtra(PlayerTypes eIndex, int iNewValue)
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ m_aiAttitudeExtra[eIndex] = iNewValue;
+}
+
+
+void CvPlayerAI::AI_changeAttitudeExtra(PlayerTypes eIndex, int iChange)
+{
+ AI_setAttitudeExtra(eIndex, (AI_getAttitudeExtra(eIndex) + iChange));
+}
+
+
+bool CvPlayerAI::AI_isFirstContact(PlayerTypes eIndex) const
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ return m_abFirstContact[eIndex];
+}
+
+
+void CvPlayerAI::AI_setFirstContact(PlayerTypes eIndex, bool bNewValue)
+{
+ FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
+ m_abFirstContact[eIndex] = bNewValue;
+}
+
+
+int CvPlayerAI::AI_getContactTimer(PlayerTypes eIndex1, ContactTypes eIndex2) const
+{
+ FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex1 < MAX_PLAYERS, "eIndex1 is expected to be within maximum bounds (invalid Index)");
+ FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex2 < NUM_CONTACT_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");
+ return m_aaiContactTimer[eIndex1][eIndex2];
+}
+
+
+void CvPlayerAI::AI_changeContactTimer(PlayerTypes eIndex1, ContactTypes eIndex2, int iChange)
+{
+ FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex1 < MAX_PLAYERS, "eIndex1 is expected to be within maximum bounds (invalid Index)");
+ FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex2 < NUM_CONTACT_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");
+ m_aaiContactTimer[eIndex1][eIndex2] = (AI_getContactTimer(eIndex1, eIndex2) + iChange);
+ FAssert(AI_getContactTimer(eIndex1, eIndex2) >= 0);
+}
+
+
+int CvPlayerAI::AI_getMemoryCount(PlayerTypes eIndex1, MemoryTypes eIndex2) const
+{
+ FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex1 < MAX_PLAYERS, "eIndex1 is expected to be within maximum bounds (invalid Index)");
+ FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex2 < NUM_MEMORY_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");
+ return m_aaiMemoryCount[eIndex1][eIndex2];
+}
+
+
+void CvPlayerAI::AI_changeMemoryCount(PlayerTypes eIndex1, MemoryTypes eIndex2, int iChange)
+{
+ FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex1 < MAX_PLAYERS, "eIndex1 is expected to be within maximum bounds (invalid Index)");
+ FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
+ FAssertMsg(eIndex2 < NUM_MEMORY_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");
+ m_aaiMemoryCount[eIndex1][eIndex2] += iChange;
+ FAssert(AI_getMemoryCount(eIndex1, eIndex2) >= 0);
+}
+
+int CvPlayerAI::AI_calculateGoldenAgeValue() const
+{
+ int iValue;
+ int iTempValue;
+ int iI;
+
+ iValue = 0;
+ for (iI = 0; iI < NUM_YIELD_TYPES; ++iI)
+ {
+ iTempValue = (GC.getYieldInfo((YieldTypes)iI).getGoldenAgeYield() * AI_yieldWeight((YieldTypes)iI));
+ iTempValue /= std::max(1, (1 + GC.getYieldInfo((YieldTypes)iI).getGoldenAgeYieldThreshold()));
+ iValue += iTempValue;
+ }
+
+ iValue *= getTotalPopulation();
+ iValue *= GC.getGameINLINE().goldenAgeLength();
+ iValue /= 100;
+
+ return iValue;
+}
+
+// Protected Functions...
+
+void CvPlayerAI::AI_doCounter()
+{
+ int iBonusImports;
+ int iI, iJ;
+
+ for (iI = 0; iI < MAX_PLAYERS; iI++)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isAlive())
+ {
+ if (GET_PLAYER((PlayerTypes)iI).getTeam() != getTeam())
+ {
+ if (GET_TEAM(getTeam()).isHasMet(GET_PLAYER((PlayerTypes)iI).getTeam()))
+ {
+ if ((getStateReligion() != NO_RELIGION) &&
+ (getStateReligion() == GET_PLAYER((PlayerTypes)iI).getStateReligion()))
+ {
+ AI_changeSameReligionCounter(((PlayerTypes)iI), 1);
+ }
+ else
+ {
+ if (AI_getSameReligionCounter((PlayerTypes)iI) > 0)
+ {
+ AI_changeSameReligionCounter(((PlayerTypes)iI), -1);
+ }
+ }
+
+ if ((getStateReligion() != NO_RELIGION) &&
+ (GET_PLAYER((PlayerTypes)iI).getStateReligion() != NO_RELIGION) &&
+ (getStateReligion() != GET_PLAYER((PlayerTypes)iI).getStateReligion()))
+ {
+ AI_changeDifferentReligionCounter(((PlayerTypes)iI), 1);
+ }
+ else
+ {
+ if (AI_getDifferentReligionCounter((PlayerTypes)iI) > 0)
+ {
+ AI_changeDifferentReligionCounter(((PlayerTypes)iI), -1);
+ }
+ }
+
+ if (GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivic() != NO_CIVIC)
+ {
+ if (isCivic((CivicTypes)(GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivic())) &&
+ GET_PLAYER((PlayerTypes)iI).isCivic((CivicTypes)(GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivic())))
+ {
+ AI_changeFavoriteCivicCounter(((PlayerTypes)iI), 1);
+ }
+ else
+ {
+ if (AI_getFavoriteCivicCounter((PlayerTypes)iI) > 0)
+ {
+ AI_changeFavoriteCivicCounter(((PlayerTypes)iI), -1);
+ }
+ }
+ }
+
+ iBonusImports = getNumTradeBonusImports((PlayerTypes)iI);
+
+ if (iBonusImports > 0)
+ {
+ AI_changeBonusTradeCounter(((PlayerTypes)iI), iBonusImports);
+ }
+ else
+ {
+ AI_changeBonusTradeCounter(((PlayerTypes)iI), -(std::min(AI_getBonusTradeCounter((PlayerTypes)iI), ((GET_PLAYER((PlayerTypes)iI).getNumCities() / 4) + 1))));
+ }
+ }
+ }
+ }
+ }
+
+ for (iI = 0; iI < MAX_PLAYERS; iI++)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isAlive())
+ {
+ for (iJ = 0; iJ < NUM_CONTACT_TYPES; iJ++)
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), ((ContactTypes)iJ)) > 0)
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), ((ContactTypes)iJ), -1);
+ }
+ }
+ }
+ }
+
+ for (iI = 0; iI < MAX_PLAYERS; iI++)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isAlive())
+ {
+ for (iJ = 0; iJ < NUM_MEMORY_TYPES; iJ++)
+ {
+ if (AI_getMemoryCount(((PlayerTypes)iI), ((MemoryTypes)iJ)) > 0)
+ {
+ if (GC.getLeaderHeadInfo(getPersonalityType()).getMemoryDecayRand(iJ) > 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getMemoryDecayRand(iJ), "Memory Decay") == 0)
+ {
+ AI_changeMemoryCount(((PlayerTypes)iI), ((MemoryTypes)iJ), -1);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void CvPlayerAI::AI_doMilitary()
+{
+ if (GET_TEAM(getTeam()).getAnyWarPlanCount(true) == 0)
+ {
+ while (AI_isFinancialTrouble() && (calculateUnitCost() > 0))
+ {
+ if (!AI_disbandUnit(1, false))
+ {
+ break;
+ }
+ }
+ }
+
+
+
+ AI_setAttackOddsChange(GC.getLeaderHeadInfo(getPersonalityType()).getBaseAttackOddsChange() +
+ GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getAttackOddsChangeRand(), "AI Attack Odds Change #1") +
+ GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getAttackOddsChangeRand(), "AI Attack Odds Change #2"));
+}
+
+
+void CvPlayerAI::AI_doResearch()
+{
+ FAssertMsg(!isHuman(), "isHuman did not return false as expected");
+
+ if (getCurrentResearch() == NO_TECH)
+ {
+ AI_chooseResearch();
+ AI_forceUpdateStrategies(); //to account for current research.
+ }
+}
+
+
+void CvPlayerAI::AI_doCommerce()
+{
+ CvCity* pLoopCity;
+ int iIdealPercent;
+ int iGoldTarget;
+ int iLoop;
+
+ FAssertMsg(!isHuman(), "isHuman did not return false as expected");
+
+ iGoldTarget = AI_goldTarget();
+ int iTargetTurns = 4 * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getResearchPercent();
+ iTargetTurns /= 100;
+ iTargetTurns = std::max(3, iTargetTurns);
+
+ if (isCommerceFlexible(COMMERCE_RESEARCH) && !AI_avoidScience())
+ {
+ // set research rate to 100%
+ setCommercePercent(COMMERCE_RESEARCH, 100);
+
+ // if the gold rate is under 0 at 90% research
+ int iGoldRate = calculateGoldRate();
+ if (iGoldRate < 0)
+ {
+ TechTypes eCurrentResearch = getCurrentResearch();
+ if (eCurrentResearch != NO_TECH)
+ {
+ int iResearchTurnsLeft = getResearchTurnsLeft(eCurrentResearch, true);
+
+ // if we can finish the current research without running out of gold, let us spend 2/3rds of our gold
+ if (getGold() >= iResearchTurnsLeft * iGoldRate)
+ {
+ iGoldTarget /= 3;
+ }
+ }
+ }
+ }
+
+ bool bReset = false;
+
+ if (isCommerceFlexible(COMMERCE_CULTURE))
+ {
+ if (getCommercePercent(COMMERCE_CULTURE) > 0)
+ {
+ setCommercePercent(COMMERCE_CULTURE, 0);
+
+ bReset = true;
+ }
+ }
+
+ if (isCommerceFlexible(COMMERCE_ESPIONAGE))
+ {
+ if (getCommercePercent(COMMERCE_ESPIONAGE) > 0)
+ {
+ setCommercePercent(COMMERCE_ESPIONAGE, 0);
+
+ for (int iTeam = 0; iTeam < MAX_CIV_TEAMS; ++iTeam)
+ {
+ setEspionageSpendingWeightAgainstTeam((TeamTypes)iTeam, 0);
+ }
+
+ bReset = true;
+ }
+ }
+
+ if (bReset)
+ {
+ AI_assignWorkingPlots();
+ }
+
+ bool bFirstTech = AI_isFirstTech(getCurrentResearch());
+ if (isCommerceFlexible(COMMERCE_CULTURE))
+ {
+ if (getNumCities() > 0)
+ {
+ iIdealPercent = 0;
+
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ if (pLoopCity->getCommerceHappinessPer(COMMERCE_CULTURE) > 0)
+ {
+ iIdealPercent += ((pLoopCity->angryPopulation() * 100) / pLoopCity->getCommerceHappinessPer(COMMERCE_CULTURE));
+ }
+ }
+
+ iIdealPercent /= getNumCities();
+
+ iIdealPercent -= (iIdealPercent % GC.getDefineINT("COMMERCE_PERCENT_CHANGE_INCREMENTS"));
+
+ iIdealPercent = std::min(iIdealPercent, 20);
+
+ if (AI_isDoStrategy(AI_STRATEGY_CULTURE4))
+ {
+ iIdealPercent = 100;
+ }
+
+ setCommercePercent(COMMERCE_CULTURE, iIdealPercent);
+ }
+ }
+
+ if (isCommerceFlexible(COMMERCE_RESEARCH))
+ {
+ if ((isNoResearchAvailable() || AI_isDoStrategy(AI_STRATEGY_CULTURE4)) && !bFirstTech)
+ {
+ setCommercePercent(COMMERCE_RESEARCH, 0);
+ }
+ else
+ {
+ while (calculateGoldRate() > 0)
+ {
+ changeCommercePercent(COMMERCE_RESEARCH, GC.getDefineINT("COMMERCE_PERCENT_CHANGE_INCREMENTS"));
+
+ if (getCommercePercent(COMMERCE_RESEARCH) == 100)
+ {
+ break;
+ }
+ }
+
+ if (getGold() + iTargetTurns * calculateGoldRate() < iGoldTarget)
+ {
+ while (getGold() + iTargetTurns * calculateGoldRate() <= iGoldTarget)
+ {
+ changeCommercePercent(COMMERCE_RESEARCH, -(GC.getDefineINT("COMMERCE_PERCENT_CHANGE_INCREMENTS")));
+
+ if ((getCommercePercent(COMMERCE_RESEARCH) == 0))
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (AI_avoidScience())
+ {
+ changeCommercePercent(COMMERCE_RESEARCH, -(GC.getDefineINT("COMMERCE_PERCENT_CHANGE_INCREMENTS")));
+ }
+ }
+
+ if ((GET_TEAM(getTeam()).getChosenWarCount(true) > 0) || (GET_TEAM(getTeam()).getWarPlanCount(WARPLAN_ATTACKED_RECENT, true) > 0))
+ {
+ changeCommercePercent(COMMERCE_RESEARCH, -(GC.getDefineINT("COMMERCE_PERCENT_CHANGE_INCREMENTS")));
+ }
+
+ if ((getCommercePercent(COMMERCE_RESEARCH) == 0) && (calculateGoldRate() > 0))
+ {
+ setCommercePercent(COMMERCE_RESEARCH, GC.getDefineINT("COMMERCE_PERCENT_CHANGE_INCREMENTS"));
+ }
+ }
+ }
+
+ if (isCommerceFlexible(COMMERCE_ESPIONAGE) && !bFirstTech)
+ {
+ int iEspionageTargetRate = 0;
+
+ for (int iTeam = 0; iTeam < MAX_CIV_TEAMS; ++iTeam)
+ {
+ CvTeam& kLoopTeam = GET_TEAM((TeamTypes)iTeam);
+ if (kLoopTeam.isAlive() && iTeam != getTeam() && !kLoopTeam.isVassal(getTeam()) && !GET_TEAM(getTeam()).isVassal((TeamTypes)iTeam))
+ {
+ int iTarget = (kLoopTeam.getEspionagePointsAgainstTeam(getTeam()) - GET_TEAM(getTeam()).getEspionagePointsAgainstTeam((TeamTypes)iTeam)) / 8;
+
+ iTarget -= GET_TEAM(getTeam()).AI_getAttitudeVal((TeamTypes)iTeam);
+
+ if (iTarget > 0)
+ {
+ iEspionageTargetRate += iTarget;
+ changeEspionageSpendingWeightAgainstTeam((TeamTypes)iTeam, iTarget);
+ }
+ }
+ }
+
+ //if economy is weak, neglect espionage spending.
+ //instead invest hammers into espionage via spies/builds
+ if (AI_isFinancialTrouble() || AI_isDoStrategy(AI_STRATEGY_CULTURE3))
+ {
+ //can still get trickle espionage income
+ iEspionageTargetRate = 0;
+ }
+ else
+ {
+ iEspionageTargetRate *= (110 - getCommercePercent(COMMERCE_GOLD) * 2);
+ iEspionageTargetRate /= 110;
+
+ iEspionageTargetRate *= GC.getLeaderHeadInfo(getLeaderType()).getEspionageWeight();
+ iEspionageTargetRate /= 100;
+
+ int iInitialResearchPercent = getCommercePercent(COMMERCE_RESEARCH);
+
+ while (getCommerceRate(COMMERCE_ESPIONAGE) < iEspionageTargetRate && getCommercePercent(COMMERCE_ESPIONAGE) < 20)
+ {
+ changeCommercePercent(COMMERCE_RESEARCH, -GC.getDefineINT("COMMERCE_PERCENT_CHANGE_INCREMENTS"));
+ changeCommercePercent(COMMERCE_ESPIONAGE, GC.getDefineINT("COMMERCE_PERCENT_CHANGE_INCREMENTS"));
+
+ if (getGold() + iTargetTurns * calculateGoldRate() < iGoldTarget)
+ {
+ break;
+ }
+
+ if (!AI_avoidScience() && !isNoResearchAvailable())
+ {
+ // if (2 * getCommercePercent(COMMERCE_RESEARCH) < iInitialResearchPercent)
+ // {
+ // break;
+ // }
+ if (getCommercePercent(COMMERCE_RESEARCH) * 2 <= (getCommercePercent(COMMERCE_ESPIONAGE) + GC.getDefineINT("COMMERCE_PERCENT_CHANGE_INCREMENTS")) * 3)
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (!bFirstTech && (getGold() < iGoldTarget) && (getCommercePercent(COMMERCE_RESEARCH) > 40))
+ {
+ bool bHurryGold = false;
+ for (int iHurry = 0; iHurry < GC.getNumHurryInfos(); iHurry++)
+ {
+ if ((GC.getHurryInfo((HurryTypes)iHurry).getGoldPerProduction() > 0) && canHurry((HurryTypes)iHurry))
+ {
+ bHurryGold = true;
+ break;
+ }
+ }
+ if (bHurryGold)
+ {
+ if (getCommercePercent(COMMERCE_ESPIONAGE) > 0)
+ {
+ changeCommercePercent(COMMERCE_ESPIONAGE, -GC.getDefineINT("COMMERCE_PERCENT_CHANGE_INCREMENTS"));
+ }
+ else
+ {
+ changeCommercePercent(COMMERCE_RESEARCH, -GC.getDefineINT("COMMERCE_PERCENT_CHANGE_INCREMENTS"));
+ }
+ //changeCommercePercent(COMMERCE_GOLD, GC.getDefineINT("COMMERCE_PERCENT_CHANGE_INCREMENTS"));
+ }
+ }
+
+ // this is called on doTurn, so make sure our gold is high enough keep us above zero gold.
+ verifyGoldCommercePercent();
+}
+
+
+void CvPlayerAI::AI_doCivics()
+{
+ CivicTypes* paeBestCivic;
+ int iI;
+
+ FAssertMsg(!isHuman(), "isHuman did not return false as expected");
+
+ if (AI_getCivicTimer() > 0)
+ {
+ AI_changeCivicTimer(-1);
+ return;
+ }
+
+ if (!canRevolution(NULL))
+ {
+ return;
+ }
+
+ FAssertMsg(AI_getCivicTimer() == 0, "AI Civic timer is expected to be 0");
+
+ paeBestCivic = new CivicTypes[GC.getNumCivicOptionInfos()];
+
+ for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
+ {
+ paeBestCivic[iI] = AI_bestCivic((CivicOptionTypes)iI);
+
+ if (paeBestCivic[iI] == NO_CIVIC)
+ {
+ paeBestCivic[iI] = getCivics((CivicOptionTypes)iI);
+ }
+ }
+
+ // XXX AI skips revolution???
+ if (canRevolution(paeBestCivic))
+ {
+ revolution(paeBestCivic);
+ AI_setCivicTimer((getMaxAnarchyTurns() == 0) ? (GC.getDefineINT("MIN_REVOLUTION_TURNS") * 2) : CIVIC_CHANGE_DELAY);
+ }
+
+ SAFE_DELETE_ARRAY(paeBestCivic);
+}
+
+
+void CvPlayerAI::AI_doReligion()
+{
+ ReligionTypes eBestReligion;
+
+ FAssertMsg(!isHuman(), "isHuman did not return false as expected");
+
+ if (AI_getReligionTimer() > 0)
+ {
+ AI_changeReligionTimer(-1);
+ return;
+ }
+
+ if (!canChangeReligion())
+ {
+ return;
+ }
+
+ FAssertMsg(AI_getReligionTimer() == 0, "AI Religion timer is expected to be 0");
+
+ eBestReligion = AI_bestReligion();
+
+ if (eBestReligion == NO_RELIGION)
+ {
+ eBestReligion = getStateReligion();
+ }
+
+ if (canConvert(eBestReligion))
+ {
+ convert(eBestReligion);
+ AI_setReligionTimer((getMaxAnarchyTurns() == 0) ? (GC.getDefineINT("MIN_CONVERSION_TURNS") * 2) : RELIGION_CHANGE_DELAY);
+ }
+}
+
+void CvPlayerAI::AI_doDiplo()
+{
+ PROFILE_FUNC();
+
+ CLLNode* pNode;
+ CvDiploParameters* pDiplo;
+ CvDeal* pLoopDeal;
+ CvCity* pLoopCity;
+ CvPlot* pLoopPlot;
+ CLinkList ourList;
+ CLinkList theirList;
+ bool abContacted[MAX_TEAMS];
+ TradeData item;
+ CivicTypes eFavoriteCivic;
+ BonusTypes eBestReceiveBonus;
+ BonusTypes eBestGiveBonus;
+ TechTypes eBestReceiveTech;
+ TechTypes eBestGiveTech;
+ TeamTypes eBestTeam;
+ bool bCancelDeal;
+ int iReceiveGold;
+ int iGiveGold;
+ int iGold;
+ int iGoldData;
+ int iGoldWeight;
+ int iGoldValuePercent;
+ int iCount;
+ int iPossibleCount;
+ int iValue;
+ int iBestValue;
+ int iOurValue;
+ int iTheirValue;
+ int iPass;
+ int iLoop;
+ int iI, iJ;
+
+ FAssert(!isHuman());
+ FAssert(!isMinorCiv());
+ FAssert(!isBarbarian());
+
+ // allow python to handle it
+ CyArgsList argsList;
+ argsList.add(getID());
+ long lResult=0;
+ gDLL->getPythonIFace()->callFunction(PYGameModule, "AI_doDiplo", argsList.makeFunctionArgs(), &lResult);
+ if (lResult == 1)
+ {
+ return;
+ }
+
+ iGoldValuePercent = AI_goldTradeValuePercent();
+
+ for (iI = 0; iI < MAX_TEAMS; iI++)
+ {
+ abContacted[iI] = false;
+ }
+
+ for (iPass = 0; iPass < 2; iPass++)
+ {
+ for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isAlive())
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isHuman() == (iPass == 1))
+ {
+ if (iI != getID())
+ {
+ if (GET_PLAYER((PlayerTypes)iI).getTeam() != getTeam())
+ {
+ for(pLoopDeal = GC.getGameINLINE().firstDeal(&iLoop); pLoopDeal != NULL; pLoopDeal = GC.getGameINLINE().nextDeal(&iLoop))
+ {
+ if (pLoopDeal->isCancelable(getID()))
+ {
+ if ((GC.getGameINLINE().getGameTurn() - pLoopDeal->getInitialGameTurn()) >= (GC.getDefineINT("PEACE_TREATY_LENGTH") * 2))
+ {
+ bCancelDeal = false;
+
+ if ((pLoopDeal->getFirstPlayer() == getID()) && (pLoopDeal->getSecondPlayer() == ((PlayerTypes)iI)))
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ if (!AI_considerOffer(((PlayerTypes)iI), pLoopDeal->getSecondTrades(), pLoopDeal->getFirstTrades(), -1))
+ {
+ bCancelDeal = true;
+ }
+ }
+ else
+ {
+ for (pNode = pLoopDeal->getFirstTrades()->head(); pNode; pNode = pLoopDeal->getFirstTrades()->next(pNode))
+ {
+ if (getTradeDenial(((PlayerTypes)iI), pNode->m_data) != NO_DENIAL)
+ {
+ bCancelDeal = true;
+ break;
+ }
+ }
+ }
+ }
+ else if ((pLoopDeal->getFirstPlayer() == ((PlayerTypes)iI)) && (pLoopDeal->getSecondPlayer() == getID()))
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ if (!AI_considerOffer(((PlayerTypes)iI), pLoopDeal->getFirstTrades(), pLoopDeal->getSecondTrades(), -1))
+ {
+ bCancelDeal = true;
+ }
+ }
+ else
+ {
+ for (pNode = pLoopDeal->getSecondTrades()->head(); pNode; pNode = pLoopDeal->getSecondTrades()->next(pNode))
+ {
+ if (getTradeDenial(((PlayerTypes)iI), pNode->m_data) != NO_DENIAL)
+ {
+ bCancelDeal = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (bCancelDeal)
+ {
+ if (canContact((PlayerTypes)iI) && AI_isWillingToTalk((PlayerTypes)iI))
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ ourList.clear();
+ theirList.clear();
+
+ for (pNode = pLoopDeal->headFirstTradesNode(); (pNode != NULL); pNode = pLoopDeal->nextFirstTradesNode(pNode))
+ {
+ if (pLoopDeal->getFirstPlayer() == getID())
+ {
+ ourList.insertAtEnd(pNode->m_data);
+ }
+ else
+ {
+ theirList.insertAtEnd(pNode->m_data);
+ }
+ }
+
+ for (pNode = pLoopDeal->headSecondTradesNode(); (pNode != NULL); pNode = pLoopDeal->nextSecondTradesNode(pNode))
+ {
+ if (pLoopDeal->getSecondPlayer() == getID())
+ {
+ ourList.insertAtEnd(pNode->m_data);
+ }
+ else
+ {
+ theirList.insertAtEnd(pNode->m_data);
+ }
+ }
+
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+
+ if (pLoopDeal->isVassalDeal())
+ {
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_NO_VASSAL"));
+ pDiplo->setAIContact(true);
+ gDLL->beginDiplomacy(pDiplo, ((PlayerTypes)iI));
+
+ }
+ else
+ {
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_CANCEL_DEAL"));
+ pDiplo->setAIContact(true);
+ pDiplo->setOurOfferList(theirList);
+ pDiplo->setTheirOfferList(ourList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ }
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+
+ pLoopDeal->kill(); // XXX test this for AI...
+ }
+ }
+ }
+ }
+ }
+
+ if (canContact((PlayerTypes)iI) && AI_isWillingToTalk((PlayerTypes)iI))
+ {
+ if (GET_PLAYER((PlayerTypes)iI).getTeam() == getTeam() || GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isVassal(getTeam()))
+ {
+ // XXX will it cancel this deal if it loses it's first resource???
+
+ iBestValue = 0;
+ eBestGiveBonus = NO_BONUS;
+
+ for (iJ = 0; iJ < GC.getNumBonusInfos(); iJ++)
+ {
+ if (getNumTradeableBonuses((BonusTypes)iJ) > 1)
+ {
+ if ((GET_PLAYER((PlayerTypes)iI).AI_bonusTradeVal(((BonusTypes)iJ), getID(), 1) > 0)
+ && (GET_PLAYER((PlayerTypes)iI).AI_bonusVal((BonusTypes)iJ, 1) > AI_bonusVal((BonusTypes)iJ, -1)))
+ {
+ setTradeItem(&item, TRADE_RESOURCES, iJ);
+
+ if (canTradeItem(((PlayerTypes)iI), item, true))
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "AI Bonus Trading #1"));
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestGiveBonus = ((BonusTypes)iJ);
+ }
+ }
+ }
+ }
+ }
+
+ if (eBestGiveBonus != NO_BONUS)
+ {
+ ourList.clear();
+ theirList.clear();
+
+ setTradeItem(&item, TRADE_RESOURCES, eBestGiveBonus);
+ ourList.insertAtEnd(item);
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_GIVE_HELP"));
+ pDiplo->setAIContact(true);
+ pDiplo->setTheirOfferList(ourList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ else
+ {
+ GC.getGameINLINE().implementDeal(getID(), ((PlayerTypes)iI), &ourList, &theirList);
+ }
+ }
+ }
+
+ if (GET_PLAYER((PlayerTypes)iI).getTeam() != getTeam() && GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isVassal(getTeam()))
+ {
+ iBestValue = 0;
+ eBestGiveTech = NO_TECH;
+
+ for (iJ = 0; iJ < GC.getNumTechInfos(); iJ++)
+ {
+ if (GET_TEAM(getTeam()).AI_techTrade((TechTypes)iJ, GET_PLAYER((PlayerTypes)iI).getTeam()) == NO_DENIAL)
+ {
+ setTradeItem(&item, TRADE_TECHNOLOGIES, iJ);
+
+ if (canTradeItem(((PlayerTypes)iI), item, true))
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "AI Vassal Tech gift"));
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestGiveTech = ((TechTypes)iJ);
+ }
+ }
+ }
+ }
+
+ if (eBestGiveTech != NO_TECH)
+ {
+ ourList.clear();
+ theirList.clear();
+
+ setTradeItem(&item, TRADE_TECHNOLOGIES, eBestGiveTech);
+ ourList.insertAtEnd(item);
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_GIVE_HELP"));
+ pDiplo->setAIContact(true);
+ pDiplo->setTheirOfferList(ourList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ else
+ {
+ GC.getGameINLINE().implementDeal(getID(), ((PlayerTypes)iI), &ourList, &theirList);
+ }
+ }
+ }
+
+ if (GET_PLAYER((PlayerTypes)iI).getTeam() != getTeam() && !(GET_TEAM(getTeam()).isHuman()) && (GET_PLAYER((PlayerTypes)iI).isHuman() || !(GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isHuman())))
+ {
+ FAssertMsg(!(GET_PLAYER((PlayerTypes)iI).isBarbarian()), "(GET_PLAYER((PlayerTypes)iI).isBarbarian()) did not return false as expected");
+ FAssertMsg(iI != getID(), "iI is not expected to be equal with getID()");
+
+ if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isVassal(getTeam()))
+ {
+ iBestValue = 0;
+ eBestGiveBonus = NO_BONUS;
+
+ for (iJ = 0; iJ < GC.getNumBonusInfos(); iJ++)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).getNumTradeableBonuses((BonusTypes)iJ) > 0 && getNumAvailableBonuses((BonusTypes)iJ) == 0)
+ {
+ iValue = AI_bonusTradeVal((BonusTypes)iJ, (PlayerTypes)iI, 1);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestGiveBonus = ((BonusTypes)iJ);
+ }
+ }
+ }
+
+ if (eBestGiveBonus != NO_BONUS)
+ {
+ theirList.clear();
+ ourList.clear();
+
+ setTradeItem(&item, TRADE_RESOURCES, eBestGiveBonus);
+ theirList.insertAtEnd(item);
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_VASSAL_GRANT_TRIBUTE, getID(), eBestGiveBonus);
+ if (pInfo)
+ {
+ gDLL->getInterfaceIFace()->addPopup(pInfo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ }
+ else
+ {
+ GC.getGameINLINE().implementDeal(getID(), ((PlayerTypes)iI), &ourList, &theirList);
+ }
+ }
+ }
+
+ if (!(GET_TEAM(getTeam()).isAtWar(GET_PLAYER((PlayerTypes)iI).getTeam())))
+ {
+ if (AI_getAttitude((PlayerTypes)iI) >= ATTITUDE_CAUTIOUS)
+ {
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ if (pLoopCity->getPreviousOwner() != ((PlayerTypes)iI))
+ {
+ if (((pLoopCity->getGameTurnAcquired() + 4) % 20) == (GC.getGameINLINE().getGameTurn() % 20))
+ {
+ iCount = 0;
+ iPossibleCount = 0;
+
+ for (iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
+ {
+ pLoopPlot = plotCity(pLoopCity->getX_INLINE(), pLoopCity->getY_INLINE(), iJ);
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->getOwnerINLINE() == iI)
+ {
+ iCount++;
+ }
+
+ iPossibleCount++;
+ }
+ }
+
+ if (iCount >= (iPossibleCount / 2))
+ {
+ setTradeItem(&item, TRADE_CITIES, pLoopCity->getID());
+
+ if (canTradeItem(((PlayerTypes)iI), item, true))
+ {
+ ourList.clear();
+
+ ourList.insertAtEnd(item);
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ //if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_OFFER_CITY"));
+ pDiplo->setAIContact(true);
+ pDiplo->setTheirOfferList(ourList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ else
+ {
+ GC.getGameINLINE().implementDeal(getID(), ((PlayerTypes)iI), &ourList, NULL);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (GET_TEAM(getTeam()).getLeaderID() == getID())
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_PERMANENT_ALLIANCE) == 0)
+ {
+ bool bOffered = false;
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_PERMANENT_ALLIANCE), "AI Diplo Alliance") == 0)
+ {
+ setTradeItem(&item, TRADE_PERMANENT_ALLIANCE);
+
+ if (canTradeItem(((PlayerTypes)iI), item, true) && GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true))
+ {
+ ourList.clear();
+ theirList.clear();
+
+ ourList.insertAtEnd(item);
+ theirList.insertAtEnd(item);
+
+ bOffered = true;
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_PERMANENT_ALLIANCE, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_PERMANENT_ALLIANCE));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_OFFER_DEAL"));
+ pDiplo->setAIContact(true);
+ pDiplo->setOurOfferList(theirList);
+ pDiplo->setTheirOfferList(ourList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ else
+ {
+ GC.getGameINLINE().implementDeal(getID(), ((PlayerTypes)iI), &ourList, &theirList);
+ break; // move on to next player since we are on the same team now
+ }
+ }
+ }
+
+ if (!bOffered)
+ {
+ setTradeItem(&item, TRADE_VASSAL);
+
+ if (canTradeItem((PlayerTypes)iI, item, true))
+ {
+ ourList.clear();
+ theirList.clear();
+
+ ourList.insertAtEnd(item);
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_PERMANENT_ALLIANCE, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_PERMANENT_ALLIANCE));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_OFFER_VASSAL"));
+ pDiplo->setAIContact(true);
+ pDiplo->setOurOfferList(theirList);
+ pDiplo->setTheirOfferList(ourList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ else
+ {
+ bool bAccepted = true;
+ TeamTypes eMasterTeam = GET_PLAYER((PlayerTypes)iI).getTeam();
+ for (int iTeam = 0; iTeam < MAX_CIV_TEAMS; iTeam++)
+ {
+ if (GET_TEAM((TeamTypes)iTeam).isAlive())
+ {
+ if (iTeam != getTeam() && iTeam != eMasterTeam && atWar(getTeam(), (TeamTypes)iTeam) && !atWar(eMasterTeam, (TeamTypes)iTeam))
+ {
+ if (GET_TEAM(eMasterTeam).AI_declareWarTrade((TeamTypes)iTeam, getTeam(), false) != NO_DENIAL)
+ {
+ bAccepted = false;
+ break;
+ }
+ }
+ }
+ }
+
+ if (bAccepted)
+ {
+ GC.getGameINLINE().implementDeal(getID(), ((PlayerTypes)iI), &ourList, &theirList);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman() && (GET_TEAM(getTeam()).getLeaderID() == getID()) && !GET_TEAM(getTeam()).isVassal(GET_PLAYER((PlayerTypes)iI).getTeam()))
+ {
+ if (getStateReligion() != NO_RELIGION)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).canConvert(getStateReligion()))
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_RELIGION_PRESSURE) == 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_RELIGION_PRESSURE), "AI Diplo Religion Pressure") == 0)
+ {
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_RELIGION_PRESSURE, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_RELIGION_PRESSURE));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_RELIGION_PRESSURE"));
+ pDiplo->setAIContact(true);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman() && (GET_TEAM(getTeam()).getLeaderID() == getID()) && !GET_TEAM(getTeam()).isVassal(GET_PLAYER((PlayerTypes)iI).getTeam()))
+ {
+ eFavoriteCivic = ((CivicTypes)(GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivic()));
+
+ if (eFavoriteCivic != NO_CIVIC)
+ {
+ if (isCivic(eFavoriteCivic))
+ {
+ if (GET_PLAYER((PlayerTypes)iI).canDoCivics(eFavoriteCivic) && !(GET_PLAYER((PlayerTypes)iI).isCivic(eFavoriteCivic)))
+ {
+ if (GET_PLAYER((PlayerTypes)iI).canRevolution(NULL))
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_CIVIC_PRESSURE) == 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_CIVIC_PRESSURE), "AI Diplo Civic Pressure") == 0)
+ {
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_CIVIC_PRESSURE, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_CIVIC_PRESSURE));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_CIVIC_PRESSURE"), GC.getCivicInfo(eFavoriteCivic).getTextKeyWide());
+ pDiplo->setAIContact(true);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman() && (GET_TEAM(getTeam()).getLeaderID() == getID()))
+ {
+ if ((AI_getMemoryCount(((PlayerTypes)iI), MEMORY_DECLARED_WAR) == 0) && (AI_getMemoryCount(((PlayerTypes)iI), MEMORY_HIRED_WAR_ALLY) == 0))
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_JOIN_WAR) == 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_JOIN_WAR), "AI Diplo Join War") == 0)
+ {
+ iBestValue = 0;
+ eBestTeam = NO_TEAM;
+
+ for (iJ = 0; iJ < MAX_CIV_TEAMS; iJ++)
+ {
+ if (GET_TEAM((TeamTypes)iJ).isAlive())
+ {
+ if (atWar(((TeamTypes)iJ), getTeam()) && !atWar(((TeamTypes)iJ), GET_PLAYER((PlayerTypes)iI).getTeam()))
+ {
+ if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isHasMet((TeamTypes)iJ))
+ {
+ if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).canDeclareWar((TeamTypes)iJ))
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "AI Joining War"));
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestTeam = ((TeamTypes)iJ);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (eBestTeam != NO_TEAM)
+ {
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_JOIN_WAR, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_JOIN_WAR));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_JOIN_WAR"), GET_PLAYER(GET_TEAM(eBestTeam).getLeaderID()).getCivilizationAdjectiveKey());
+ pDiplo->setAIContact(true);
+ pDiplo->setData(eBestTeam);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman() && (GET_TEAM(getTeam()).getLeaderID() == getID()) && !GET_TEAM(getTeam()).isVassal(GET_PLAYER((PlayerTypes)iI).getTeam()))
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_STOP_TRADING) == 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_STOP_TRADING), "AI Diplo Stop Trading") == 0)
+ {
+ eBestTeam = GET_TEAM(getTeam()).AI_getWorstEnemy();
+
+ if ((eBestTeam != NO_TEAM) && GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isHasMet(eBestTeam) && !GET_TEAM(eBestTeam).isVassal(GET_PLAYER((PlayerTypes)iI).getTeam()))
+ {
+ if (GET_PLAYER((PlayerTypes)iI).canStopTradingWithTeam(eBestTeam))
+ {
+ FAssert(!atWar(GET_PLAYER((PlayerTypes)iI).getTeam(), eBestTeam));
+ FAssert(GET_PLAYER((PlayerTypes)iI).getTeam() != eBestTeam);
+
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_STOP_TRADING, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_STOP_TRADING));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_STOP_TRADING"), GET_PLAYER(GET_TEAM(eBestTeam).getLeaderID()).getCivilizationAdjectiveKey());
+ pDiplo->setAIContact(true);
+ pDiplo->setData(eBestTeam);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman() && (GET_TEAM(getTeam()).getLeaderID() == getID()))
+ {
+ if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).getAssets() < (GET_TEAM(getTeam()).getAssets() / 2))
+ {
+ if (AI_getAttitude((PlayerTypes)iI) > GC.getLeaderHeadInfo(GET_PLAYER((PlayerTypes)iI).getPersonalityType()).getNoGiveHelpAttitudeThreshold())
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_GIVE_HELP) == 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_GIVE_HELP), "AI Diplo Give Help") == 0)
+ {
+ // XXX maybe do gold instead???
+
+ iBestValue = 0;
+ eBestGiveTech = NO_TECH;
+
+ for (iJ = 0; iJ < GC.getNumTechInfos(); iJ++)
+ {
+ setTradeItem(&item, TRADE_TECHNOLOGIES, iJ);
+
+ if (canTradeItem(((PlayerTypes)iI), item, true))
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "AI Giving Help"));
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestGiveTech = ((TechTypes)iJ);
+ }
+ }
+ }
+
+ if (eBestGiveTech != NO_TECH)
+ {
+ ourList.clear();
+
+ setTradeItem(&item, TRADE_TECHNOLOGIES, eBestGiveTech);
+ ourList.insertAtEnd(item);
+
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_GIVE_HELP, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_GIVE_HELP));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_GIVE_HELP"));
+ pDiplo->setAIContact(true);
+ pDiplo->setTheirOfferList(ourList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman() && (GET_TEAM(getTeam()).getLeaderID() == getID()))
+ {
+ if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).getAssets() > (GET_TEAM(getTeam()).getAssets() / 2))
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_ASK_FOR_HELP) == 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_ASK_FOR_HELP), "AI Diplo Ask For Help") == 0)
+ {
+ iBestValue = 0;
+ eBestReceiveTech = NO_TECH;
+
+ for (iJ = 0; iJ < GC.getNumTechInfos(); iJ++)
+ {
+ setTradeItem(&item, TRADE_TECHNOLOGIES, iJ);
+
+ if (GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true))
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "AI Asking For Help"));
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestReceiveTech = ((TechTypes)iJ);
+ }
+ }
+ }
+
+ if (eBestReceiveTech != NO_TECH)
+ {
+ theirList.clear();
+
+ setTradeItem(&item, TRADE_TECHNOLOGIES, eBestReceiveTech);
+ theirList.insertAtEnd(item);
+
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_ASK_FOR_HELP, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_ASK_FOR_HELP));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_ASK_FOR_HELP"));
+ pDiplo->setAIContact(true);
+ pDiplo->setOurOfferList(theirList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman() && (GET_TEAM(getTeam()).getLeaderID() == getID()))
+ {
+ if (GET_TEAM(getTeam()).canDeclareWar(GET_PLAYER((PlayerTypes)iI).getTeam()) && !GET_TEAM(getTeam()).AI_isSneakAttackPreparing(GET_PLAYER((PlayerTypes)iI).getTeam()))
+ {
+ if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).getDefensivePower() < GET_TEAM(getTeam()).getPower(true))
+ {
+ if (AI_getAttitude((PlayerTypes)iI) <= GC.getLeaderHeadInfo(GET_PLAYER((PlayerTypes)iI).getPersonalityType()).getDemandTributeAttitudeThreshold())
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_DEMAND_TRIBUTE) == 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_DEMAND_TRIBUTE), "AI Diplo Demand Tribute") == 0)
+ {
+ iReceiveGold = std::min(std::max(0, (GET_PLAYER((PlayerTypes)iI).getGold() - 50)), GET_PLAYER((PlayerTypes)iI).AI_goldTarget());
+
+ iReceiveGold -= (iReceiveGold % GC.getDefineINT("DIPLOMACY_VALUE_REMAINDER"));
+
+ if (iReceiveGold > 50)
+ {
+ theirList.clear();
+
+ setTradeItem(&item, TRADE_GOLD, iReceiveGold);
+ theirList.insertAtEnd(item);
+
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_DEMAND_TRIBUTE, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_DEMAND_TRIBUTE));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_DEMAND_TRIBUTE"));
+ pDiplo->setAIContact(true);
+ pDiplo->setOurOfferList(theirList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman() && (GET_TEAM(getTeam()).getLeaderID() == getID()))
+ {
+ if (GET_TEAM(getTeam()).canDeclareWar(GET_PLAYER((PlayerTypes)iI).getTeam()) && !GET_TEAM(getTeam()).AI_isSneakAttackPreparing(GET_PLAYER((PlayerTypes)iI).getTeam()))
+ {
+ if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).getDefensivePower() < GET_TEAM(getTeam()).getPower(true))
+ {
+ if (AI_getAttitude((PlayerTypes)iI) <= GC.getLeaderHeadInfo(GET_PLAYER((PlayerTypes)iI).getPersonalityType()).getDemandTributeAttitudeThreshold())
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_DEMAND_TRIBUTE) == 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_DEMAND_TRIBUTE), "AI Diplo Demand Tribute") == 0)
+ {
+ if (GET_TEAM(getTeam()).AI_mapTradeVal(GET_PLAYER((PlayerTypes)iI).getTeam()) > 100)
+ {
+ theirList.clear();
+
+ setTradeItem(&item, TRADE_MAPS);
+ theirList.insertAtEnd(item);
+
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_DEMAND_TRIBUTE, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_DEMAND_TRIBUTE));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_DEMAND_TRIBUTE"));
+ pDiplo->setAIContact(true);
+ pDiplo->setOurOfferList(theirList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman() && (GET_TEAM(getTeam()).getLeaderID() == getID()))
+ {
+ if (GET_TEAM(getTeam()).canDeclareWar(GET_PLAYER((PlayerTypes)iI).getTeam()) && !GET_TEAM(getTeam()).AI_isSneakAttackPreparing(GET_PLAYER((PlayerTypes)iI).getTeam()))
+ {
+ if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).getDefensivePower() < GET_TEAM(getTeam()).getPower(true))
+ {
+ if (AI_getAttitude((PlayerTypes)iI) <= GC.getLeaderHeadInfo(GET_PLAYER((PlayerTypes)iI).getPersonalityType()).getDemandTributeAttitudeThreshold())
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_DEMAND_TRIBUTE) == 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_DEMAND_TRIBUTE), "AI Diplo Demand Tribute") == 0)
+ {
+ iBestValue = 0;
+ eBestReceiveTech = NO_TECH;
+
+ for (iJ = 0; iJ < GC.getNumTechInfos(); iJ++)
+ {
+ setTradeItem(&item, TRADE_TECHNOLOGIES, iJ);
+
+ if (GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true))
+ {
+ if (GC.getGameINLINE().countKnownTechNumTeams((TechTypes)iJ) > 1)
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "AI Demanding Tribute (Tech)"));
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestReceiveTech = ((TechTypes)iJ);
+ }
+ }
+ }
+ }
+
+ if (eBestReceiveTech != NO_TECH)
+ {
+ theirList.clear();
+
+ setTradeItem(&item, TRADE_TECHNOLOGIES, eBestReceiveTech);
+ theirList.insertAtEnd(item);
+
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_DEMAND_TRIBUTE, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_DEMAND_TRIBUTE));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_DEMAND_TRIBUTE"));
+ pDiplo->setAIContact(true);
+ pDiplo->setOurOfferList(theirList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman() && (GET_TEAM(getTeam()).getLeaderID() == getID()))
+ {
+ if (GET_TEAM(getTeam()).canDeclareWar(GET_PLAYER((PlayerTypes)iI).getTeam()) && !GET_TEAM(getTeam()).AI_isSneakAttackPreparing(GET_PLAYER((PlayerTypes)iI).getTeam()))
+ {
+ if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).getDefensivePower() < GET_TEAM(getTeam()).getPower(true))
+ {
+ if (AI_getAttitude((PlayerTypes)iI) <= GC.getLeaderHeadInfo(GET_PLAYER((PlayerTypes)iI).getPersonalityType()).getDemandTributeAttitudeThreshold())
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_DEMAND_TRIBUTE) == 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_DEMAND_TRIBUTE), "AI Diplo Demand Tribute") == 0)
+ {
+ iBestValue = 0;
+ eBestReceiveBonus = NO_BONUS;
+
+ for (iJ = 0; iJ < GC.getNumBonusInfos(); iJ++)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).getNumTradeableBonuses((BonusTypes)iJ) > 1)
+ {
+ if (AI_bonusTradeVal(((BonusTypes)iJ), ((PlayerTypes)iI), 1) > 0)
+ {
+ setTradeItem(&item, TRADE_RESOURCES, iJ);
+
+ if (GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true))
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "AI Demanding Tribute (Bonus)"));
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestReceiveBonus = ((BonusTypes)iJ);
+ }
+ }
+ }
+ }
+ }
+
+ if (eBestReceiveBonus != NO_BONUS)
+ {
+ theirList.clear();
+
+ setTradeItem(&item, TRADE_RESOURCES, eBestReceiveBonus);
+ theirList.insertAtEnd(item);
+
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_DEMAND_TRIBUTE, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_DEMAND_TRIBUTE));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_DEMAND_TRIBUTE"));
+ pDiplo->setAIContact(true);
+ pDiplo->setOurOfferList(theirList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (GET_TEAM(getTeam()).getLeaderID() == getID())
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_OPEN_BORDERS) == 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_OPEN_BORDERS), "AI Diplo Open Borders") == 0)
+ {
+ setTradeItem(&item, TRADE_OPEN_BORDERS);
+
+ if (canTradeItem(((PlayerTypes)iI), item, true) && GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true))
+ {
+ ourList.clear();
+ theirList.clear();
+
+ ourList.insertAtEnd(item);
+ theirList.insertAtEnd(item);
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_OPEN_BORDERS, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_OPEN_BORDERS));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_OFFER_DEAL"));
+ pDiplo->setAIContact(true);
+ pDiplo->setOurOfferList(theirList);
+ pDiplo->setTheirOfferList(ourList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ else
+ {
+ GC.getGameINLINE().implementDeal(getID(), ((PlayerTypes)iI), &ourList, &theirList);
+ }
+ }
+ }
+ }
+ }
+
+ if (GET_TEAM(getTeam()).getLeaderID() == getID())
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_DEFENSIVE_PACT) == 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_DEFENSIVE_PACT), "AI Diplo Defensive Pact") == 0)
+ {
+ setTradeItem(&item, TRADE_DEFENSIVE_PACT);
+
+ if (canTradeItem(((PlayerTypes)iI), item, true) && GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true))
+ {
+ ourList.clear();
+ theirList.clear();
+
+ ourList.insertAtEnd(item);
+ theirList.insertAtEnd(item);
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_DEFENSIVE_PACT, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_DEFENSIVE_PACT));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_OFFER_DEAL"));
+ pDiplo->setAIContact(true);
+ pDiplo->setOurOfferList(theirList);
+ pDiplo->setTheirOfferList(ourList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ else
+ {
+ GC.getGameINLINE().implementDeal(getID(), ((PlayerTypes)iI), &ourList, &theirList);
+ }
+ }
+ }
+ }
+ }
+
+ if (!(GET_PLAYER((PlayerTypes)iI).isHuman()) || (GET_TEAM(getTeam()).getLeaderID() == getID()))
+ {
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_TRADE_TECH) == 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_TRADE_TECH), "AI Diplo Trade Tech") == 0)
+ {
+ iBestValue = 0;
+ eBestReceiveTech = NO_TECH;
+
+ for (iJ = 0; iJ < GC.getNumTechInfos(); iJ++)
+ {
+ setTradeItem(&item, TRADE_TECHNOLOGIES, iJ);
+
+ if (GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true))
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "AI Tech Trading #1"));
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestReceiveTech = ((TechTypes)iJ);
+ }
+ }
+ }
+
+ if (eBestReceiveTech != NO_TECH)
+ {
+ iBestValue = 0;
+ eBestGiveTech = NO_TECH;
+
+ for (iJ = 0; iJ < GC.getNumTechInfos(); iJ++)
+ {
+ setTradeItem(&item, TRADE_TECHNOLOGIES, iJ);
+
+ if (canTradeItem(((PlayerTypes)iI), item, true))
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "AI Tech Trading #2"));
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestGiveTech = ((TechTypes)iJ);
+ }
+ }
+ }
+
+ iOurValue = GET_TEAM(getTeam()).AI_techTradeVal(eBestReceiveTech, GET_PLAYER((PlayerTypes)iI).getTeam());
+ if (eBestGiveTech != NO_TECH)
+ {
+ iTheirValue = GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).AI_techTradeVal(eBestGiveTech, getTeam());
+ }
+ else
+ {
+ iTheirValue = 0;
+ }
+
+ iReceiveGold = 0;
+ iGiveGold = 0;
+
+ if (iTheirValue > iOurValue)
+ {
+ iGoldWeight = iTheirValue - iOurValue;
+ iGoldData = (iGoldWeight * 100) / iGoldValuePercent;
+ if (iGoldWeight * 100 > iGoldData * iGoldValuePercent)
+ {
+ iGoldData++;
+ }
+
+ iGold = std::min(iGoldData, GET_PLAYER((PlayerTypes)iI).AI_maxGoldTrade(getID()));
+
+ if (iGold > 0)
+ {
+ setTradeItem(&item, TRADE_GOLD, iGold);
+
+ if (GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true))
+ {
+ iReceiveGold = iGold;
+ iOurValue += (iGold * iGoldValuePercent) / 100;
+ }
+ }
+ }
+ else if (iOurValue > iTheirValue)
+ {
+
+ iGoldData = ((iOurValue - iTheirValue) * 100) / iGoldValuePercent;
+ iGold = std::min(iGoldData, AI_maxGoldTrade((PlayerTypes)iI));
+
+ if (iGold > 0)
+ {
+ setTradeItem(&item, TRADE_GOLD, iGold);
+
+ if (canTradeItem(((PlayerTypes)iI), item, true))
+ {
+ iGiveGold = iGold;
+ iTheirValue += (iGold * iGoldValuePercent) / 100;
+ }
+ }
+ }
+
+ if (!(GET_PLAYER((PlayerTypes)iI).isHuman()) || (iOurValue >= iTheirValue))
+ {
+ if ((iOurValue > ((iTheirValue * 2) / 3)) && (iTheirValue > ((iOurValue * 2) / 3)))
+ {
+ ourList.clear();
+ theirList.clear();
+
+ if (eBestGiveTech != NO_TECH)
+ {
+ setTradeItem(&item, TRADE_TECHNOLOGIES, eBestGiveTech);
+ ourList.insertAtEnd(item);
+ }
+
+ setTradeItem(&item, TRADE_TECHNOLOGIES, eBestReceiveTech);
+ theirList.insertAtEnd(item);
+
+ if (iGiveGold != 0)
+ {
+ setTradeItem(&item, TRADE_GOLD, iGiveGold);
+ ourList.insertAtEnd(item);
+ }
+
+ if (iReceiveGold != 0)
+ {
+ setTradeItem(&item, TRADE_GOLD, iReceiveGold);
+ theirList.insertAtEnd(item);
+ }
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_TRADE_TECH, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_TRADE_TECH));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_OFFER_DEAL"));
+ pDiplo->setAIContact(true);
+ pDiplo->setOurOfferList(theirList);
+ pDiplo->setTheirOfferList(ourList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ else
+ {
+ GC.getGameINLINE().implementDeal(getID(), ((PlayerTypes)iI), &ourList, &theirList);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_TRADE_BONUS) == 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_TRADE_BONUS), "AI Diplo Trade Bonus") == 0)
+ {
+ iBestValue = 0;
+ eBestReceiveBonus = NO_BONUS;
+
+ for (iJ = 0; iJ < GC.getNumBonusInfos(); iJ++)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).getNumTradeableBonuses((BonusTypes)iJ) > 1)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).AI_corporationBonusVal((BonusTypes)iJ) == 0)
+ {
+ if (AI_bonusTradeVal(((BonusTypes)iJ), ((PlayerTypes)iI), 1) > 0)
+ {
+ setTradeItem(&item, TRADE_RESOURCES, iJ);
+
+ if (GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true))
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "AI Bonus Trading #1"));
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestReceiveBonus = ((BonusTypes)iJ);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (eBestReceiveBonus != NO_BONUS)
+ {
+ iBestValue = 0;
+ eBestGiveBonus = NO_BONUS;
+
+ for (iJ = 0; iJ < GC.getNumBonusInfos(); iJ++)
+ {
+ if (iJ != eBestReceiveBonus)
+ {
+ if (getNumTradeableBonuses((BonusTypes)iJ) > 1)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).AI_bonusTradeVal(((BonusTypes)iJ), getID(), 1) > 0)
+ {
+ setTradeItem(&item, TRADE_RESOURCES, iJ);
+
+ if (canTradeItem(((PlayerTypes)iI), item, true))
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "AI Bonus Trading #2"));
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestGiveBonus = ((BonusTypes)iJ);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (eBestGiveBonus != NO_BONUS)
+ {
+ if (!(GET_PLAYER((PlayerTypes)iI).isHuman()) || (AI_bonusTradeVal(eBestReceiveBonus, ((PlayerTypes)iI), -1) >= GET_PLAYER((PlayerTypes)iI).AI_bonusTradeVal(eBestGiveBonus, getID(), 1)))
+ {
+ ourList.clear();
+ theirList.clear();
+
+ setTradeItem(&item, TRADE_RESOURCES, eBestGiveBonus);
+ ourList.insertAtEnd(item);
+
+ setTradeItem(&item, TRADE_RESOURCES, eBestReceiveBonus);
+ theirList.insertAtEnd(item);
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_TRADE_BONUS, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_TRADE_BONUS));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_OFFER_DEAL"));
+ pDiplo->setAIContact(true);
+ pDiplo->setOurOfferList(theirList);
+ pDiplo->setTheirOfferList(ourList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ else
+ {
+ GC.getGameINLINE().implementDeal(getID(), ((PlayerTypes)iI), &ourList, &theirList);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (AI_getContactTimer(((PlayerTypes)iI), CONTACT_TRADE_MAP) == 0)
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getContactRand(CONTACT_TRADE_MAP), "AI Diplo Trade Map") == 0)
+ {
+ setTradeItem(&item, TRADE_MAPS);
+
+ if (GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true) && canTradeItem(((PlayerTypes)iI), item, true))
+ {
+ if (!(GET_PLAYER((PlayerTypes)iI).isHuman()) || (GET_TEAM(getTeam()).AI_mapTradeVal(GET_PLAYER((PlayerTypes)iI).getTeam()) >= GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).AI_mapTradeVal(getTeam())))
+ {
+ ourList.clear();
+ theirList.clear();
+
+ setTradeItem(&item, TRADE_MAPS);
+ ourList.insertAtEnd(item);
+
+ setTradeItem(&item, TRADE_MAPS);
+ theirList.insertAtEnd(item);
+
+ if (GET_PLAYER((PlayerTypes)iI).isHuman())
+ {
+ if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ AI_changeContactTimer(((PlayerTypes)iI), CONTACT_TRADE_MAP, GC.getLeaderHeadInfo(getPersonalityType()).getContactDelay(CONTACT_TRADE_MAP));
+ pDiplo = new CvDiploParameters(getID());
+ FAssertMsg(pDiplo != NULL, "pDiplo must be valid");
+ pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_OFFER_DEAL"));
+ pDiplo->setAIContact(true);
+ pDiplo->setOurOfferList(theirList);
+ pDiplo->setTheirOfferList(ourList);
+ gDLL->beginDiplomacy(pDiplo, (PlayerTypes)iI);
+ abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
+ }
+ }
+ else
+ {
+ GC.getGameINLINE().implementDeal(getID(), ((PlayerTypes)iI), &ourList, &theirList);
+ }
+ }
+ }
+ }
+ }
+
+ if (!(GET_PLAYER((PlayerTypes)iI).isHuman()) || !(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
+ {
+ int iDeclareWarTradeRand = GC.getLeaderHeadInfo(getPersonalityType()).getDeclareWarTradeRand();
+ int iMinAtWarCounter = MAX_INT;
+ for (iJ = 0; iJ < MAX_CIV_TEAMS; iJ++)
+ {
+ if (GET_TEAM((TeamTypes)iJ).isAlive())
+ {
+ if (atWar(((TeamTypes)iJ), getTeam()))
+ {
+ int iAtWarCounter = GET_TEAM(getTeam()).AI_getAtWarCounter((TeamTypes)iJ);
+ if (GET_TEAM(getTeam()).AI_getWarPlan((TeamTypes)iJ) == WARPLAN_DOGPILE)
+ {
+ iAtWarCounter *= 2;
+ iAtWarCounter += 5;
+ }
+ iMinAtWarCounter = std::min(iAtWarCounter, iMinAtWarCounter);
+ }
+ }
+ }
+
+ if (iMinAtWarCounter < 10)
+ {
+ iDeclareWarTradeRand *= iMinAtWarCounter;
+ iDeclareWarTradeRand /= 10;
+ iDeclareWarTradeRand ++;
+ }
+
+ if (iMinAtWarCounter < 4)
+ {
+ iDeclareWarTradeRand /= 4;
+ iDeclareWarTradeRand ++;
+ }
+
+ if (GC.getGameINLINE().getSorenRandNum(iDeclareWarTradeRand, "AI Diplo Declare War Trade") == 0)
+ {
+ iBestValue = 0;
+ eBestTeam = NO_TEAM;
+
+ for (iJ = 0; iJ < MAX_CIV_TEAMS; iJ++)
+ {
+ if (GET_TEAM((TeamTypes)iJ).isAlive())
+ {
+ if (atWar(((TeamTypes)iJ), getTeam()) && !atWar(((TeamTypes)iJ), GET_PLAYER((PlayerTypes)iI).getTeam()))
+ {
+ if (GET_TEAM((TeamTypes)iJ).getAtWarCount(true) < std::max(2, (GC.getGameINLINE().countCivTeamsAlive() / 2)))
+ {
+ setTradeItem(&item, TRADE_WAR, iJ);
+
+ if (GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true))
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(1000, "AI Declare War Trading"));
+
+ iValue *= (101 + GET_TEAM((TeamTypes)iJ).AI_getAttitudeWeight(getTeam()));
+ iValue /= 100;
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestTeam = ((TeamTypes)iJ);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (eBestTeam != NO_TEAM)
+ {
+ iBestValue = 0;
+ eBestGiveTech = NO_TECH;
+
+ for (iJ = 0; iJ < GC.getNumTechInfos(); iJ++)
+ {
+ setTradeItem(&item, TRADE_TECHNOLOGIES, iJ);
+
+ if (canTradeItem(((PlayerTypes)iI), item, true))
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(100, "AI Tech Trading #2"));
+
+ iValue *= GET_TEAM(eBestTeam).getResearchLeft((TechTypes)iJ);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestGiveTech = ((TechTypes)iJ);
+ }
+ }
+ }
+
+ iOurValue = GET_TEAM(getTeam()).AI_declareWarTradeVal(eBestTeam, GET_PLAYER((PlayerTypes)iI).getTeam());
+ if (eBestGiveTech != NO_TECH)
+ {
+ iTheirValue = GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).AI_techTradeVal(eBestGiveTech, getTeam());
+ }
+ else
+ {
+ iTheirValue = 0;
+ }
+
+ int iBestValue2 = 0;
+ TechTypes eBestGiveTech2 = NO_TECH;
+
+ if ((iTheirValue < iOurValue) && (eBestGiveTech != NO_TECH))
+ {
+ for (iJ = 0; iJ < GC.getNumTechInfos(); iJ++)
+ {
+ if (iJ != eBestGiveTech)
+ {
+ setTradeItem(&item, TRADE_TECHNOLOGIES, iJ);
+
+ if (canTradeItem(((PlayerTypes)iI), item, true))
+ {
+ iValue = (1 + GC.getGameINLINE().getSorenRandNum(100, "AI Tech Trading #2"));
+
+ iValue *= GET_TEAM(eBestTeam).getResearchLeft((TechTypes)iJ);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue2 = iValue;
+ eBestGiveTech2 = ((TechTypes)iJ);
+ }
+ }
+ }
+ }
+
+ if (eBestGiveTech2 != NO_TECH)
+ {
+ iTheirValue += GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).AI_techTradeVal(eBestGiveTech2, getTeam());
+ }
+ }
+
+ iReceiveGold = 0;
+ iGiveGold = 0;
+
+ if (iTheirValue > iOurValue)
+ {
+ iGold = std::min(((iTheirValue - iOurValue) * 100) / iGoldValuePercent, GET_PLAYER((PlayerTypes)iI).AI_maxGoldTrade(getID()));
+
+ if (iGold > 0)
+ {
+ setTradeItem(&item, TRADE_GOLD, iGold);
+
+ if (GET_PLAYER((PlayerTypes)iI).canTradeItem(getID(), item, true))
+ {
+ iReceiveGold = iGold;
+ iOurValue += (iGold * iGoldValuePercent) / 100;
+ }
+ }
+ }
+ else if (iOurValue > iTheirValue)
+ {
+ iGold = std::min(((iOurValue - iTheirValue) * 100) / iGoldValuePercent, AI_maxGoldTrade((PlayerTypes)iI));
+
+ if (iGold > 0)
+ {
+ setTradeItem(&item, TRADE_GOLD, iGold);
+
+ if (canTradeItem(((PlayerTypes)iI), item, true))
+ {
+ iGiveGold = iGold;
+ iTheirValue += (iGold * iGoldValuePercent) / 100;
+ }
+ }
+ }
+
+ if (iTheirValue > (iOurValue * 3 / 4))
+ {
+ ourList.clear();
+ theirList.clear();
+
+ if (eBestGiveTech != NO_TECH)
+ {
+ setTradeItem(&item, TRADE_TECHNOLOGIES, eBestGiveTech);
+ ourList.insertAtEnd(item);
+ }
+
+ if (eBestGiveTech2 != NO_TECH)
+ {
+ setTradeItem(&item, TRADE_TECHNOLOGIES, eBestGiveTech2);
+ ourList.insertAtEnd(item);
+ }
+
+ setTradeItem(&item, TRADE_WAR, eBestTeam);
+ theirList.insertAtEnd(item);
+
+ if (iGiveGold != 0)
+ {
+ setTradeItem(&item, TRADE_GOLD, iGiveGold);
+ ourList.insertAtEnd(item);
+ }
+
+ if (iReceiveGold != 0)
+ {
+ setTradeItem(&item, TRADE_GOLD, iReceiveGold);
+ theirList.insertAtEnd(item);
+ }
+
+ GC.getGameINLINE().implementDeal(getID(), ((PlayerTypes)iI), &ourList, &theirList);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+//
+// read object from a stream
+// used during load
+//
+void CvPlayerAI::read(FDataStreamBase* pStream)
+{
+ CvPlayer::read(pStream); // read base class data first
+
+ uint uiFlag=0;
+ pStream->Read(&uiFlag); // flags for expansion
+
+ pStream->Read(&m_iPeaceWeight);
+ pStream->Read(&m_iEspionageWeight);
+ pStream->Read(&m_iAttackOddsChange);
+ pStream->Read(&m_iCivicTimer);
+ pStream->Read(&m_iReligionTimer);
+ pStream->Read(&m_iExtraGoldTarget);
+
+ pStream->Read(&m_iStrategyHash);
+ pStream->Read(&m_iStrategyHashCacheTurn);
+ pStream->Read(&m_iAveragesCacheTurn);
+ pStream->Read(&m_iAverageGreatPeopleMultiplier);
+
+ pStream->Read(NUM_YIELD_TYPES, m_aiAverageYieldMultiplier);
+ pStream->Read(NUM_COMMERCE_TYPES, m_aiAverageCommerceMultiplier);
+ pStream->Read(NUM_COMMERCE_TYPES, m_aiAverageCommerceExchange);
+
+ pStream->Read(&m_iUpgradeUnitsCacheTurn);
+ pStream->Read(&m_iUpgradeUnitsCachedExpThreshold);
+ pStream->Read(&m_iUpgradeUnitsCachedGold);
+
+ pStream->Read(NUM_UNITAI_TYPES, m_aiNumTrainAIUnits);
+ pStream->Read(NUM_UNITAI_TYPES, m_aiNumAIUnits);
+ pStream->Read(MAX_PLAYERS, m_aiSameReligionCounter);
+ pStream->Read(MAX_PLAYERS, m_aiDifferentReligionCounter);
+ pStream->Read(MAX_PLAYERS, m_aiFavoriteCivicCounter);
+ pStream->Read(MAX_PLAYERS, m_aiBonusTradeCounter);
+ pStream->Read(MAX_PLAYERS, m_aiPeacetimeTradeValue);
+ pStream->Read(MAX_PLAYERS, m_aiPeacetimeGrantValue);
+ pStream->Read(MAX_PLAYERS, m_aiGoldTradedTo);
+ pStream->Read(MAX_PLAYERS, m_aiAttitudeExtra);
+
+ pStream->Read(MAX_PLAYERS, m_abFirstContact);
+
+ for (int i = 0; i < MAX_PLAYERS; i++)
+ {
+ pStream->Read(NUM_CONTACT_TYPES, m_aaiContactTimer[i]);
+ }
+ for (int i = 0; i < MAX_PLAYERS; i++)
+ {
+ pStream->Read(NUM_MEMORY_TYPES, m_aaiMemoryCount[i]);
+ }
+
+
+
+ pStream->Read(&m_bWasFinancialTrouble);
+ pStream->Read(&m_iTurnLastProductionDirty);
+
+ {
+ m_aiAICitySites.clear();
+ uint iSize;
+ pStream->Read(&iSize);
+ for (uint i = 0; i < iSize; i++)
+ {
+ int iCitySite;
+ pStream->Read(&iCitySite);
+ m_aiAICitySites.push_back(iCitySite);
+ }
+ }
+
+ pStream->Read(GC.getNumBonusInfos(), m_aiBonusValue);
+ pStream->Read(GC.getNumUnitClassInfos(), m_aiUnitClassWeights);
+ pStream->Read(GC.getNumUnitCombatInfos(), m_aiUnitCombatWeights);
+ pStream->Read(MAX_PLAYERS, m_aiCloseBordersAttitudeCache);
+}
+
+
+//
+// save object to a stream
+// used during save
+//
+void CvPlayerAI::write(FDataStreamBase* pStream)
+{
+ CvPlayer::write(pStream); // write base class data first
+
+ uint uiFlag=0;
+ pStream->Write(uiFlag); // flag for expansion
+
+ pStream->Write(m_iPeaceWeight);
+ pStream->Write(m_iEspionageWeight);
+ pStream->Write(m_iAttackOddsChange);
+ pStream->Write(m_iCivicTimer);
+ pStream->Write(m_iReligionTimer);
+ pStream->Write(m_iExtraGoldTarget);
+
+ pStream->Write(m_iStrategyHash);
+ pStream->Write(m_iStrategyHashCacheTurn);
+ pStream->Write(m_iAveragesCacheTurn);
+ pStream->Write(m_iAverageGreatPeopleMultiplier);
+
+ pStream->Write(NUM_YIELD_TYPES, m_aiAverageYieldMultiplier);
+ pStream->Write(NUM_COMMERCE_TYPES, m_aiAverageCommerceMultiplier);
+ pStream->Write(NUM_COMMERCE_TYPES, m_aiAverageCommerceExchange);
+
+ pStream->Write(m_iUpgradeUnitsCacheTurn);
+ pStream->Write(m_iUpgradeUnitsCachedExpThreshold);
+ pStream->Write(m_iUpgradeUnitsCachedGold);
+
+ pStream->Write(NUM_UNITAI_TYPES, m_aiNumTrainAIUnits);
+ pStream->Write(NUM_UNITAI_TYPES, m_aiNumAIUnits);
+ pStream->Write(MAX_PLAYERS, m_aiSameReligionCounter);
+ pStream->Write(MAX_PLAYERS, m_aiDifferentReligionCounter);
+ pStream->Write(MAX_PLAYERS, m_aiFavoriteCivicCounter);
+ pStream->Write(MAX_PLAYERS, m_aiBonusTradeCounter);
+ pStream->Write(MAX_PLAYERS, m_aiPeacetimeTradeValue);
+ pStream->Write(MAX_PLAYERS, m_aiPeacetimeGrantValue);
+ pStream->Write(MAX_PLAYERS, m_aiGoldTradedTo);
+ pStream->Write(MAX_PLAYERS, m_aiAttitudeExtra);
+
+ pStream->Write(MAX_PLAYERS, m_abFirstContact);
+
+ for (int i = 0; i < MAX_PLAYERS; i++)
+ {
+ pStream->Write(NUM_CONTACT_TYPES, m_aaiContactTimer[i]);
+ }
+ for (int i = 0; i < MAX_PLAYERS; i++)
+ {
+ pStream->Write(NUM_MEMORY_TYPES, m_aaiMemoryCount[i]);
+ }
+
+ pStream->Write(m_bWasFinancialTrouble);
+ pStream->Write(m_iTurnLastProductionDirty);
+
+ {
+ uint iSize = m_aiAICitySites.size();
+ pStream->Write(iSize);
+ std::vector::iterator it;
+ for (it = m_aiAICitySites.begin(); it != m_aiAICitySites.end(); ++it)
+ {
+ pStream->Write((*it));
+ }
+ }
+
+ pStream->Write(GC.getNumBonusInfos(), m_aiBonusValue);
+ pStream->Write(GC.getNumUnitClassInfos(), m_aiUnitClassWeights);
+ pStream->Write(GC.getNumUnitCombatInfos(), m_aiUnitCombatWeights);
+ pStream->Write(MAX_PLAYERS, m_aiCloseBordersAttitudeCache);
+}
+
+
+int CvPlayerAI::AI_eventValue(EventTypes eEvent, const EventTriggeredData& kTriggeredData) const
+{
+ CvEventTriggerInfo& kTrigger = GC.getEventTriggerInfo(kTriggeredData.m_eTrigger);
+ CvEventInfo& kEvent = GC.getEventInfo(eEvent);
+
+ int iNumCities = getNumCities();
+ CvCity* pCity = getCity(kTriggeredData.m_iCityId);
+ CvPlot* pPlot = GC.getMapINLINE().plot(kTriggeredData.m_iPlotX, kTriggeredData.m_iPlotY);
+ CvUnit* pUnit = getUnit(kTriggeredData.m_iUnitId);
+
+ int iHappy = 0;
+ int iHealth = 0;
+ int aiYields[NUM_YIELD_TYPES];
+ int aiCommerceYields[NUM_COMMERCE_TYPES];
+
+ for (int iI = 0; iI < NUM_YIELD_TYPES; iI++)
+ {
+ aiYields[iI] = 0;
+ }
+ for (int iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
+ {
+ aiCommerceYields[iI] = 0;
+ }
+
+ if (NO_PLAYER != kTriggeredData.m_eOtherPlayer)
+ {
+ if (kEvent.isDeclareWar())
+ {
+ switch (AI_getAttitude(kTriggeredData.m_eOtherPlayer))
+ {
+ case ATTITUDE_FURIOUS:
+ case ATTITUDE_ANNOYED:
+ case ATTITUDE_CAUTIOUS:
+ if (GET_TEAM(getTeam()).getDefensivePower() < GET_TEAM(GET_PLAYER(kTriggeredData.m_eOtherPlayer).getTeam()).getPower(true))
+ {
+ return -MAX_INT + 1;
+ }
+ break;
+ case ATTITUDE_PLEASED:
+ case ATTITUDE_FRIENDLY:
+ return -MAX_INT + 1;
+ break;
+ }
+ }
+ }
+
+ //Proportional to #turns in the game...
+ //(AI evaluation will generally assume proper game speed scaling!)
+ int iGameSpeedPercent = GC.getGameSpeedInfo(GC.getGame().getGameSpeedType()).getVictoryDelayPercent();
+
+ int iValue = GC.getGameINLINE().getSorenRandNum(kEvent.getAIValue(), "AI Event choice");
+ iValue += (getEventCost(eEvent, kTriggeredData.m_eOtherPlayer, false) + getEventCost(eEvent, kTriggeredData.m_eOtherPlayer, true)) / 2;
+
+ iValue += kEvent.getEspionagePoints();
+
+ if (kEvent.getTech() != NO_TECH)
+ {
+ iValue += (GET_TEAM(getTeam()).getResearchCost((TechTypes)kEvent.getTech()) * kEvent.getTechPercent()) / 100;
+ }
+
+ if (kEvent.getUnitClass() != NO_UNITCLASS)
+ {
+ UnitTypes eUnit = (UnitTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(kEvent.getUnitClass());
+ if (eUnit != NO_UNIT)
+ {
+ //Altough AI_unitValue compares well within units, the value is somewhat independent of cost
+ int iUnitValue = GC.getUnitInfo(eUnit).getProductionCost();
+ if (iUnitValue > 0)
+ {
+ iUnitValue *= 2;
+ }
+ else if (iUnitValue == -1)
+ {
+ iUnitValue = 200; //Great Person?
+ }
+
+ iUnitValue *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getTrainPercent();
+ iValue += kEvent.getNumUnits() * iUnitValue;
+ }
+ }
+
+ if (kEvent.isDisbandUnit())
+ {
+ CvUnit* pUnit = getUnit(kTriggeredData.m_iUnitId);
+ if (NULL != pUnit)
+ {
+ int iUnitValue = pUnit->getUnitInfo().getProductionCost();
+ if (iUnitValue > 0)
+ {
+ iUnitValue *= 2;
+ }
+ else if (iUnitValue == -1)
+ {
+ iUnitValue = 200; //Great Person?
+ }
+
+ iUnitValue *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getTrainPercent();
+ iValue -= iUnitValue;
+ }
+ }
+
+ if (kEvent.getBuildingClass() != NO_BUILDINGCLASS)
+ {
+ BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(kEvent.getBuildingClass());
+ if (eBuilding != NO_BUILDING)
+ {
+ if (pCity)
+ {
+ //iValue += kEvent.getBuildingChange() * pCity->AI_buildingValue(eBuilding);
+ int iBuildingValue = GC.getBuildingInfo(eBuilding).getProductionCost();
+ if (iBuildingValue > 0)
+ {
+ iBuildingValue *= 2;
+ }
+ else if (iBuildingValue == -1)
+ {
+ iBuildingValue = 300; //Shrine?
+ }
+
+ iBuildingValue *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getConstructPercent();
+ iValue += kEvent.getBuildingChange() * iBuildingValue;
+ }
+ }
+ }
+
+ TechTypes eBestTech = NO_TECH;
+ int iBestValue = 0;
+ for (int iTech = 0; iTech < GC.getNumTechInfos(); ++iTech)
+ {
+ if (canResearch((TechTypes)iTech))
+ {
+ if (NO_PLAYER == kTriggeredData.m_eOtherPlayer || GET_TEAM(GET_PLAYER(kTriggeredData.m_eOtherPlayer).getTeam()).isHasTech((TechTypes)iTech))
+ {
+ int iValue = 0;
+ for (int i = 0; i < GC.getNumFlavorTypes(); ++i)
+ {
+ iValue += kEvent.getTechFlavorValue(i) * GC.getTechInfo((TechTypes)iTech).getFlavorValue(i);
+ }
+
+ if (iValue > iBestValue)
+ {
+ eBestTech = (TechTypes)iTech;
+ iBestValue = iValue;
+ }
+ }
+ }
+ }
+
+ if (eBestTech != NO_TECH)
+ {
+ iValue += (GET_TEAM(getTeam()).getResearchCost(eBestTech) * kEvent.getTechPercent()) / 100;
+ }
+
+ if (kEvent.isGoldenAge())
+ {
+ iValue += AI_calculateGoldenAgeValue();
+ }
+
+ { //Yield and other changes
+ if (kEvent.getNumBuildingYieldChanges() > 0)
+ {
+ for (int iBuildingClass = 0; iBuildingClass < GC.getNumBuildingClassInfos(); ++iBuildingClass)
+ {
+ for (int iYield = 0; iYield < NUM_YIELD_TYPES; ++iYield)
+ {
+ aiYields[iYield] += kEvent.getBuildingYieldChange(iBuildingClass, iYield);
+ }
+ }
+ }
+
+ if (kEvent.getNumBuildingCommerceChanges() > 0)
+ {
+ for (int iBuildingClass = 0; iBuildingClass < GC.getNumBuildingClassInfos(); ++iBuildingClass)
+ {
+ for (int iCommerce = 0; iCommerce < NUM_COMMERCE_TYPES; ++iCommerce)
+ {
+ aiCommerceYields[iCommerce] += kEvent.getBuildingCommerceChange(iBuildingClass, iCommerce);
+ }
+ }
+ }
+
+ if (kEvent.getNumBuildingHappyChanges() > 0)
+ {
+ for (int iBuildingClass = 0; iBuildingClass < GC.getNumBuildingClassInfos(); ++iBuildingClass)
+ {
+ iHappy += kEvent.getBuildingHappyChange(iBuildingClass);
+ }
+ }
+
+ if (kEvent.getNumBuildingHealthChanges() > 0)
+ {
+ for (int iBuildingClass = 0; iBuildingClass < GC.getNumBuildingClassInfos(); ++iBuildingClass)
+ {
+ iHealth += kEvent.getBuildingHealthChange(iBuildingClass);
+ }
+ }
+ }
+
+ if (kEvent.isCityEffect())
+ {
+ int iCityPopulation = -1;
+ int iCityTurnValue = 0;
+ if (NULL != pCity)
+ {
+ iCityPopulation = pCity->getPopulation();
+ for (int iSpecialist = 0; iSpecialist < GC.getNumSpecialistInfos(); ++iSpecialist)
+ {
+ if (kEvent.getFreeSpecialistCount(iSpecialist) > 0)
+ {
+ iCityTurnValue += (pCity->AI_specialistValue((SpecialistTypes)iSpecialist, false, false) / 300);
+ }
+ }
+ }
+
+ if (-1 == iCityPopulation)
+ {
+ //What is going on here?
+ iCityPopulation = 5;
+ }
+
+ iCityTurnValue += ((iHappy + kEvent.getHappy()) * 8);
+ iCityTurnValue += ((iHealth + kEvent.getHealth()) * 6);
+
+ iCityTurnValue += aiYields[YIELD_FOOD] * 5;
+ iCityTurnValue += aiYields[YIELD_PRODUCTION] * 5;
+ iCityTurnValue += aiYields[YIELD_COMMERCE] * 3;
+
+ iCityTurnValue += aiCommerceYields[COMMERCE_RESEARCH] * 3;
+ iCityTurnValue += aiCommerceYields[COMMERCE_GOLD] * 3;
+ iCityTurnValue += aiCommerceYields[COMMERCE_CULTURE] * 1;
+ iCityTurnValue += aiCommerceYields[COMMERCE_ESPIONAGE] * 2;
+
+ iValue += (iCityTurnValue * 20 * iGameSpeedPercent) / 100;
+
+ iValue += kEvent.getFood();
+ iValue += kEvent.getFoodPercent() / 4;
+ iValue += kEvent.getPopulationChange() * 30;
+ iValue -= kEvent.getRevoltTurns() * (12 + iCityPopulation * 16);
+ iValue -= (kEvent.getHurryAnger() * 6 * GC.getDefineINT("HURRY_ANGER_DIVISOR") * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getHurryConscriptAngerPercent()) / 100;
+ iValue += kEvent.getHappyTurns() * 10;
+ iValue += kEvent.getCulture() / 2;
+ }
+ else if (!kEvent.isOtherPlayerCityEffect())
+ {
+ int iPerTurnValue = 0;
+ iPerTurnValue += iNumCities * ((iHappy * 4) + (kEvent.getHappy() * 8));
+ iPerTurnValue += iNumCities * ((iHealth * 3) + (kEvent.getHealth() * 6));
+
+ iValue += (iPerTurnValue * 20 * iGameSpeedPercent) / 100;
+
+ iValue += (kEvent.getFood() * iNumCities);
+ iValue += (kEvent.getFoodPercent() * iNumCities) / 4;
+ iValue += (kEvent.getPopulationChange() * iNumCities * 40);
+ iValue -= (iNumCities * kEvent.getHurryAnger() * 6 * GC.getDefineINT("HURRY_ANGER_DIVISOR") * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getHurryConscriptAngerPercent()) / 100;
+ iValue += iNumCities * kEvent.getHappyTurns() * 10;
+ iValue += iNumCities * kEvent.getCulture() / 2;
+ }
+
+ int iBonusValue = 0;
+ if (NO_BONUS != kEvent.getBonus())
+ {
+ iBonusValue = AI_bonusVal((BonusTypes)kEvent.getBonus());
+ }
+
+ if (NULL != pPlot)
+ {
+ if (kEvent.getFeatureChange() != 0)
+ {
+ int iOldFeatureValue = 0;
+ int iNewFeatureValue = 0;
+ if (pPlot->getFeatureType() != NO_FEATURE)
+ {
+ //*grumble* who tied feature production to builds rather than the feature...
+ iOldFeatureValue = GC.getFeatureInfo(pPlot->getFeatureType()).getHealthPercent();
+
+ if (kEvent.getFeatureChange() > 0)
+ {
+ FeatureTypes eFeature = (FeatureTypes)kEvent.getFeature();
+ FAssert(eFeature != NO_FEATURE);
+ if (eFeature != NO_FEATURE)
+ {
+ iNewFeatureValue = GC.getFeatureInfo(eFeature).getHealthPercent();
+ }
+ }
+
+ iValue += ((iNewFeatureValue - iOldFeatureValue) * iGameSpeedPercent) / 100;
+ }
+ }
+
+ if (kEvent.getImprovementChange() > 0)
+ {
+ iValue += (30 * iGameSpeedPercent) / 100;
+ }
+ else if (kEvent.getImprovementChange() < 0)
+ {
+ iValue -= (30 * iGameSpeedPercent) / 100;
+ }
+
+ if (kEvent.getRouteChange() > 0)
+ {
+ iValue += (10 * iGameSpeedPercent) / 100;
+ }
+ else if (kEvent.getRouteChange() < 0)
+ {
+ iValue -= (10 * iGameSpeedPercent) / 100;
+ }
+
+ if (kEvent.getBonusChange() > 0)
+ {
+ iValue += (iBonusValue * 15 * iGameSpeedPercent) / 100;
+ }
+ else if (kEvent.getBonusChange() < 0)
+ {
+ iValue -= (iBonusValue * 15 * iGameSpeedPercent) / 100;
+ }
+
+ for (int i = 0; i < NUM_YIELD_TYPES; ++i)
+ {
+ if (0 != kEvent.getPlotExtraYield(i))
+ {
+ if (pPlot->getWorkingCity() != NULL)
+ {
+ FAssertMsg(pPlot->getWorkingCity()->getOwner() == getID(), "Event creates a boni for another player?");
+ aiYields[i] += kEvent.getPlotExtraYield(i);
+ }
+ else
+ {
+ iValue += (20 * 8 * kEvent.getPlotExtraYield(i) * iGameSpeedPercent) / 100;
+ }
+ }
+ }
+ }
+
+ if (NO_BONUS != kEvent.getBonusRevealed())
+ {
+ iValue += (iBonusValue * 10 * iGameSpeedPercent) / 100;
+ }
+
+ if (NULL != pUnit)
+ {
+ iValue += (2 * pUnit->baseCombatStr() * kEvent.getUnitExperience() * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getTrainPercent()) / 100;
+
+ iValue -= 10 * kEvent.getUnitImmobileTurns();
+ }
+
+ {
+ int iPromotionValue = 0;
+
+ for (int i = 0; i < GC.getNumUnitCombatInfos(); ++i)
+ {
+ if (NO_PROMOTION != kEvent.getUnitCombatPromotion(i))
+ {
+ int iLoop;
+ for (CvUnit* pLoopUnit = firstUnit(&iLoop); NULL != pLoopUnit; pLoopUnit = nextUnit(&iLoop))
+ {
+ if (pLoopUnit->getUnitCombatType() == i)
+ {
+ if (!pLoopUnit->isHasPromotion((PromotionTypes)kEvent.getUnitCombatPromotion(i)))
+ {
+ iPromotionValue += 5 * pLoopUnit->baseCombatStr();
+ }
+ }
+ }
+
+ iPromotionValue += iNumCities * 50;
+ }
+ }
+
+ iValue += (iPromotionValue * iGameSpeedPercent) / 100;
+ }
+
+ if (kEvent.getFreeUnitSupport() != 0)
+ {
+ iValue += (20 * kEvent.getFreeUnitSupport() * iGameSpeedPercent) / 100;
+ }
+
+ if (kEvent.getInflationModifier() != 0)
+ {
+ iValue -= (20 * kEvent.getInflationModifier() * calculatePreInflatedCosts() * iGameSpeedPercent) / 100;
+ }
+
+ if (kEvent.getSpaceProductionModifier() != 0)
+ {
+ iValue += ((20 + iNumCities) * getSpaceProductionModifier() * iGameSpeedPercent) / 100;
+ }
+
+ int iOtherPlayerAttitudeWeight = 0;
+ if (kTriggeredData.m_eOtherPlayer != NO_PLAYER)
+ {
+ iOtherPlayerAttitudeWeight = AI_getAttitudeWeight(kTriggeredData.m_eOtherPlayer);
+ iOtherPlayerAttitudeWeight += 10 - GC.getGame().getSorenRandNum(20, "AI event value attitude");
+ }
+
+ //Religion
+ if (kTriggeredData.m_eReligion != NO_RELIGION)
+ {
+ ReligionTypes eReligion = kTriggeredData.m_eReligion;
+
+ int iReligionValue = 15;
+
+ if (getStateReligion() == eReligion)
+ {
+ iReligionValue += 15;
+ }
+ if (hasHolyCity(eReligion))
+ {
+ iReligionValue += 15;
+ }
+
+ iValue += (kEvent.getConvertOwnCities() * iReligionValue * iGameSpeedPercent) / 100;
+
+ if (kEvent.getConvertOtherCities() > 0)
+ {
+ //Don't like them much = fairly indifferent, hate them = negative.
+ iValue += (kEvent.getConvertOtherCities() * (iOtherPlayerAttitudeWeight + 50) * iReligionValue * iGameSpeedPercent) / 15000;
+ }
+ }
+
+ if (NO_PLAYER != kTriggeredData.m_eOtherPlayer)
+ {
+ CvPlayerAI& kOtherPlayer = GET_PLAYER(kTriggeredData.m_eOtherPlayer);
+
+ int iDiploValue = 0;
+ //if we like this player then value positive attitude, if however we really hate them then
+ //actually value negative attitude.
+ iDiploValue += ((iOtherPlayerAttitudeWeight + 50) * kEvent.getAttitudeModifier() * GET_PLAYER(kTriggeredData.m_eOtherPlayer).getPower()) / std::max(1, getPower());
+
+ if (kEvent.getTheirEnemyAttitudeModifier() != 0)
+ {
+ //Oh wow this sure is mildly complicated.
+ TeamTypes eWorstEnemy = GET_TEAM(GET_PLAYER(kTriggeredData.m_eOtherPlayer).getTeam()).AI_getWorstEnemy();
+
+ if (NO_TEAM != eWorstEnemy && eWorstEnemy != getTeam())
+ {
+ int iThirdPartyAttitudeWeight = GET_TEAM(getTeam()).AI_getAttitudeWeight(eWorstEnemy);
+
+ //If we like both teams, we want them to get along.
+ //If we like otherPlayer but not enemy (or vice-verca), we don't want them to get along.
+ //If we don't like either, we don't want them to get along.
+ //Also just value stirring up trouble in general.
+
+ int iThirdPartyDiploValue = 50 * kEvent.getTheirEnemyAttitudeModifier();
+ iThirdPartyDiploValue *= (iThirdPartyAttitudeWeight - 10);
+ iThirdPartyDiploValue *= (iOtherPlayerAttitudeWeight - 10);
+ iThirdPartyDiploValue /= 10000;
+
+ if ((iOtherPlayerAttitudeWeight) < 0 && (iThirdPartyAttitudeWeight < 0))
+ {
+ iThirdPartyDiploValue *= -1;
+ }
+
+ iThirdPartyDiploValue /= 2;
+
+ iDiploValue += iThirdPartyDiploValue;
+ }
+ }
+
+ iDiploValue *= iGameSpeedPercent;
+ iDiploValue /= 100;
+
+ if (NO_BONUS != kEvent.getBonusGift())
+ {
+ int iBonusValue = -AI_bonusVal((BonusTypes)kEvent.getBonusGift(), -1);
+ iBonusValue += (iOtherPlayerAttitudeWeight - 40) * kOtherPlayer.AI_bonusVal((BonusTypes)kEvent.getBonusGift(), +1);
+ //Positive for friends, negative for enemies.
+ iDiploValue += (iBonusValue * GC.getDefineINT("PEACE_TREATY_LENGTH")) / 60;
+ }
+
+ if (GC.getGameINLINE().isOption(GAMEOPTION_AGGRESSIVE_AI))
+ {
+ //What is this "relationships" thing?
+ iDiploValue /= 2;
+ }
+
+ if (kEvent.isGoldToPlayer())
+ {
+ //If the gold goes to another player instead of the void, then this is a positive
+ //thing if we like the player, otherwise it's a negative thing.
+ int iGiftValue = (getEventCost(eEvent, kTriggeredData.m_eOtherPlayer, false) + getEventCost(eEvent, kTriggeredData.m_eOtherPlayer, true)) / 2;
+ iGiftValue *= -iOtherPlayerAttitudeWeight;
+ iGiftValue /= 110;
+
+ iValue += iGiftValue;
+ }
+
+ if (kEvent.isDeclareWar())
+ {
+ int iWarValue = (GET_TEAM(getTeam()).getDefensivePower() - GET_TEAM(GET_PLAYER(kTriggeredData.m_eOtherPlayer).getTeam()).getPower(true));// / std::max(1, GET_TEAM(getTeam()).getDefensivePower());
+ iWarValue -= 30 * AI_getAttitudeVal(kTriggeredData.m_eOtherPlayer);
+ }
+
+ if (kEvent.getMaxPillage() > 0)
+ {
+ int iPillageValue = (40 * (kEvent.getMinPillage() + kEvent.getMaxPillage())) / 2;
+ //If we hate them, this is good to do.
+ iPillageValue *= 25 - iOtherPlayerAttitudeWeight;
+ iPillageValue *= iGameSpeedPercent;
+ iPillageValue /= 12500;
+ }
+
+ iValue += (iDiploValue * iGameSpeedPercent) / 100;
+ }
+
+ int iThisEventValue = iValue;
+ //XXX THIS IS VULNERABLE TO NON-TRIVIAL RECURSIONS!
+ //Event A effects Event B, Event B effects Event A
+ for (int iEvent = 0; iEvent < GC.getNumEventInfos(); ++iEvent)
+ {
+ if (kEvent.getAdditionalEventChance(iEvent) > 0)
+ {
+ if (iEvent == eEvent)
+ {
+ //Infinite recursion is not our friend.
+ //Fortunately we have the event value for this event - sans values of other events
+ //disabled or cleared. Hopefully no events will be that complicated...
+ //Double the value since it's recursive.
+ iValue += (kEvent.getAdditionalEventChance(iEvent) * iThisEventValue) / 50;
+ }
+ else
+ {
+ iValue += (kEvent.getAdditionalEventChance(iEvent) * AI_eventValue((EventTypes)iEvent, kTriggeredData)) / 100;
+ }
+ }
+
+ if (kEvent.getClearEventChance(iEvent) > 0)
+ {
+ if (iEvent == eEvent)
+ {
+ iValue -= (kEvent.getClearEventChance(iEvent) * iThisEventValue) / 50;
+ }
+ else
+ {
+ iValue -= (kEvent.getClearEventChance(iEvent) * AI_eventValue((EventTypes)iEvent, kTriggeredData)) / 100;
+ }
+ }
+ }
+
+ iValue *= 100 + GC.getGameINLINE().getSorenRandNum(20, "AI Event choice");
+ iValue /= 100;
+
+ return iValue;
+}
+
+EventTypes CvPlayerAI::AI_chooseEvent(int iTriggeredId) const
+{
+ EventTriggeredData* pTriggeredData = getEventTriggered(iTriggeredId);
+ if (NULL == pTriggeredData)
+ {
+ return NO_EVENT;
+ }
+
+ CvEventTriggerInfo& kTrigger = GC.getEventTriggerInfo(pTriggeredData->m_eTrigger);
+
+ int iBestValue = -MAX_INT;
+ EventTypes eBestEvent = NO_EVENT;
+
+ for (int i = 0; i < kTrigger.getNumEvents(); i++)
+ {
+ int iValue = -MAX_INT;
+ if (kTrigger.getEvent(i) != NO_EVENT)
+ {
+ CvEventInfo& kEvent = GC.getEventInfo((EventTypes)kTrigger.getEvent(i));
+ if (canDoEvent((EventTypes)kTrigger.getEvent(i), *pTriggeredData))
+ {
+ iValue = AI_eventValue((EventTypes)kTrigger.getEvent(i), *pTriggeredData);
+ }
+ }
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestEvent = (EventTypes)kTrigger.getEvent(i);
+ }
+ }
+
+ return eBestEvent;
+}
+
+void CvPlayerAI::AI_doSplit()
+{
+ PROFILE_FUNC();
+
+ if (!canSplitEmpire())
+ {
+ return;
+ }
+
+ int iLoop;
+ std::map mapAreaValues;
+
+ for (CvArea* pLoopArea = GC.getMapINLINE().firstArea(&iLoop); pLoopArea != NULL; pLoopArea = GC.getMapINLINE().nextArea(&iLoop))
+ {
+ mapAreaValues[pLoopArea->getID()] = 0;
+ }
+
+ for (CvCity* pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ mapAreaValues[pLoopCity->area()->getID()] += pLoopCity->AI_cityValue();
+ }
+
+ std::map::iterator it;
+ for (it = mapAreaValues.begin(); it != mapAreaValues.end(); ++it)
+ {
+ if (it->second < 0)
+ {
+ int iAreaId = it->first;
+
+ if (canSplitArea(iAreaId))
+ {
+ splitEmpire(iAreaId);
+
+ for (CvUnit* pUnit = firstUnit(&iLoop); pUnit != NULL; pUnit = nextUnit(&iLoop))
+ {
+ if (pUnit->area()->getID() == iAreaId)
+ {
+ TeamTypes ePlotTeam = pUnit->plot()->getTeam();
+
+ if (NO_TEAM != ePlotTeam)
+ {
+ CvTeam& kPlotTeam = GET_TEAM(ePlotTeam);
+ if (kPlotTeam.isVassal(getTeam()) && GET_TEAM(getTeam()).isParent(ePlotTeam))
+ {
+ pUnit->gift();
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+void CvPlayerAI::AI_launch(VictoryTypes eVictory)
+{
+ if (GET_TEAM(getTeam()).isHuman())
+ {
+ return;
+ }
+
+ if (!GET_TEAM(getTeam()).canLaunch(eVictory))
+ {
+ return;
+ }
+
+ bool bLaunch = true;
+
+ int iBestArrival = MAX_INT;
+ TeamTypes eBestTeam = NO_TEAM;
+
+ for (int iTeam = 0; iTeam < MAX_CIV_TEAMS; ++iTeam)
+ {
+ if (iTeam != getTeam())
+ {
+ CvTeam& kTeam = GET_TEAM((TeamTypes)iTeam);
+ if (kTeam.isAlive())
+ {
+ int iCountdown = kTeam.getVictoryCountdown(eVictory);
+ if (iCountdown > 0)
+ {
+ if (iCountdown < iBestArrival)
+ {
+ iBestArrival = iCountdown;
+ eBestTeam = (TeamTypes)iTeam;
+ }
+
+ if (iCountdown < GET_TEAM(getTeam()).getVictoryDelay(eVictory) && kTeam.getLaunchSuccessRate(eVictory) == 100)
+ {
+ bLaunch = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (bLaunch)
+ {
+ if (NO_TEAM == eBestTeam || iBestArrival > GET_TEAM(getTeam()).getVictoryDelay(eVictory))
+ {
+ if (GET_TEAM(getTeam()).getLaunchSuccessRate(eVictory) < 100)
+ {
+ bLaunch = false;
+ }
+ }
+ }
+
+ if (bLaunch)
+ {
+ launch(eVictory);
+ }
+}
+
+void CvPlayerAI::AI_doCheckFinancialTrouble()
+{
+ // if we just ran into financial trouble this turn
+ bool bFinancialTrouble = AI_isFinancialTrouble();
+ if (bFinancialTrouble != m_bWasFinancialTrouble)
+ {
+ if (bFinancialTrouble)
+ {
+ int iGameTurn = GC.getGameINLINE().getGameTurn();
+
+ // only reset at most every 10 turns
+ if (iGameTurn > m_iTurnLastProductionDirty + 10)
+ {
+ // redeterimine the best things to build in each city
+ AI_makeProductionDirty();
+
+ m_iTurnLastProductionDirty = iGameTurn;
+ }
+ }
+
+ m_bWasFinancialTrouble = bFinancialTrouble;
+ }
+}
+
+bool CvPlayerAI::AI_disbandUnit(int iExpThreshold, bool bObsolete)
+{
+ CvUnit* pLoopUnit;
+ CvUnit* pBestUnit;
+ int iValue;
+ int iBestValue;
+ int iLoop;
+
+ iBestValue = MAX_INT;
+ pBestUnit = NULL;
+
+ for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
+ {
+ if (!(pLoopUnit->hasCargo()))
+ {
+ if (!(pLoopUnit->isGoldenAge()))
+ {
+ if (pLoopUnit->getUnitInfo().getProductionCost() > 0)
+ {
+ if ((iExpThreshold == -1) || (pLoopUnit->canFight() && pLoopUnit->getExperience() <= iExpThreshold))
+ {
+ if (!(pLoopUnit->isMilitaryHappiness()) || !(pLoopUnit->plot()->isCity()) || (pLoopUnit->plot()->plotCount(PUF_isMilitaryHappiness, -1, -1, getID()) > 2))
+ {
+ iValue = (10000 + GC.getGameINLINE().getSorenRandNum(1000, "Disband Unit"));
+
+ iValue *= 100 + (pLoopUnit->getUnitInfo().getProductionCost() * 3);
+ iValue /= 100;
+
+ iValue *= 100 + (pLoopUnit->getExperience() * 10);
+ iValue /= 100;
+
+ iValue *= 100 + (pLoopUnit->getLevel() * 25);
+ iValue /= 100;
+
+ if (pLoopUnit->canDefend() && pLoopUnit->plot()->isCity())
+ {
+ iValue *= 2;
+ }
+
+ if (pLoopUnit->plot()->getTeam() == pLoopUnit->getTeam())
+ {
+ iValue *= 3;
+ }
+
+ switch (pLoopUnit->AI_getUnitAIType())
+ {
+ case UNITAI_UNKNOWN:
+ case UNITAI_ANIMAL:
+ break;
+
+ case UNITAI_SETTLE:
+ iValue *= 20;
+ break;
+
+ case UNITAI_WORKER:
+ if ((GC.getGame().getGameTurn() - pLoopUnit->getGameTurnCreated()) > 10)
+ {
+ if (pLoopUnit->plot()->isCity())
+ {
+ if (pLoopUnit->plot()->getPlotCity()->AI_getWorkersNeeded() == 0)
+ {
+ iValue *= 10;
+ }
+ }
+ }
+ break;
+
+ case UNITAI_ATTACK:
+ case UNITAI_ATTACK_CITY:
+ case UNITAI_COLLATERAL:
+ case UNITAI_PILLAGE:
+ case UNITAI_RESERVE:
+ case UNITAI_COUNTER:
+ iValue *= 2;
+ break;
+
+ case UNITAI_CITY_DEFENSE:
+ case UNITAI_CITY_COUNTER:
+ case UNITAI_CITY_SPECIAL:
+ case UNITAI_PARADROP:
+ iValue *= 6;
+ break;
+
+ case UNITAI_EXPLORE:
+ iValue *= 15;
+ break;
+
+ case UNITAI_MISSIONARY:
+ iValue *= 8;
+ break;
+
+ case UNITAI_PROPHET:
+ case UNITAI_ARTIST:
+ case UNITAI_SCIENTIST:
+ case UNITAI_GENERAL:
+ case UNITAI_MERCHANT:
+ case UNITAI_ENGINEER:
+ break;
+
+ case UNITAI_SPY:
+ iValue *= 12;
+ break;
+
+ case UNITAI_ICBM:
+ iValue *= 4;
+ break;
+
+ case UNITAI_WORKER_SEA:
+ iValue *= 18;
+ break;
+
+ case UNITAI_ATTACK_SEA:
+ case UNITAI_RESERVE_SEA:
+ case UNITAI_ESCORT_SEA:
+ break;
+
+ case UNITAI_EXPLORE_SEA:
+ iValue *= 25;
+ break;
+
+ case UNITAI_ASSAULT_SEA:
+ case UNITAI_SETTLER_SEA:
+ case UNITAI_MISSIONARY_SEA:
+ case UNITAI_SPY_SEA:
+ case UNITAI_CARRIER_SEA:
+ case UNITAI_MISSILE_CARRIER_SEA:
+ iValue *= 5;
+ break;
+
+ case UNITAI_PIRATE_SEA:
+ case UNITAI_ATTACK_AIR:
+ break;
+
+ case UNITAI_DEFENSE_AIR:
+ case UNITAI_CARRIER_AIR:
+ case UNITAI_MISSILE_AIR:
+ iValue *= 3;
+ break;
+
+ default:
+ FAssert(false);
+ break;
+ }
+
+ if (pLoopUnit->getUnitInfo().getExtraCost() > 0)
+ {
+ iValue /= (pLoopUnit->getUnitInfo().getExtraCost() + 1);
+ }
+
+ if (iValue < iBestValue)
+ {
+ iBestValue = iValue;
+ pBestUnit = pLoopUnit;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (pBestUnit != NULL)
+ {
+ pBestUnit->kill(false);
+ return true;
+ }
+ return false;
+}
+
+int CvPlayerAI::AI_cultureVictoryTechValue(TechTypes eTech) const
+{
+ int iI;
+
+ if (eTech == NO_TECH)
+ {
+ return 0;
+ }
+
+ int iValue = 0;
+
+ if (GC.getTechInfo(eTech).isDefensivePactTrading())
+ {
+ iValue += 50;
+ }
+
+ if (GC.getTechInfo(eTech).isCommerceFlexible(COMMERCE_CULTURE))
+ {
+ iValue += 100;
+ }
+
+ //units
+ bool bAnyWarplan = (GET_TEAM(getTeam()).getAnyWarPlanCount(true) > 0);
+ int iBestUnitValue = 0;
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ UnitTypes eLoopUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI)));
+
+ if (eLoopUnit != NO_UNIT)
+ {
+ if (isTechRequiredForUnit((eTech), eLoopUnit))
+ {
+ int iTempValue = (GC.getUnitInfo(eLoopUnit).getCombat() * 100) / std::max(1, (GC.getGame().getBestLandUnitCombat()));
+ iTempValue *= bAnyWarplan ? 2 : 1;
+
+ iValue += iTempValue / 3;
+ iBestUnitValue = std::max(iBestUnitValue, iTempValue);
+ }
+ }
+ }
+ iValue += std::max(0, iBestUnitValue - 15);
+
+ //cultural things
+ for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
+ {
+ BuildingTypes eLoopBuilding = ((BuildingTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iI)));
+
+ if (eLoopBuilding != NO_BUILDING)
+ {
+ if (isTechRequiredForBuilding((eTech), eLoopBuilding))
+ {
+ CvBuildingInfo& kLoopBuilding = GC.getBuildingInfo(eLoopBuilding);
+
+ if ((GC.getBuildingClassInfo((BuildingClassTypes)iI).getDefaultBuildingIndex()) != (GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iI)))
+ {
+ //UB
+ iValue += 100;
+ }
+
+ iValue += (150 * kLoopBuilding.getCommerceChange(COMMERCE_CULTURE)) * 20;
+ iValue += kLoopBuilding.getCommerceModifier(COMMERCE_CULTURE) * 2;
+ }
+ }
+ }
+
+ //important civics
+ for (iI = 0; iI < GC.getNumCivicInfos(); iI++)
+ {
+ if (GC.getCivicInfo((CivicTypes)iI).getTechPrereq() == eTech)
+ {
+ iValue += GC.getCivicInfo((CivicTypes)iI).getCommerceModifier(COMMERCE_CULTURE) * 2;
+ }
+ }
+
+ return iValue;
+}
+
+int CvPlayerAI::AI_getCultureVictoryStage() const
+{
+ int iValue;
+
+ if (!GC.getGameINLINE().culturalVictoryValid())
+ {
+ return 0;
+ }
+
+ if (getCapitalCity() == NULL)
+ {
+ return 0;
+ }
+
+ if (getCapitalCity()->getGameTurnFounded() > (10 + GC.getGameINLINE().getStartTurn()))
+ {
+ //the loss of the capital indicates it might be a good idea to abort any culture victory
+ return 0;
+ }
+
+ if (GC.getGame().getStartEra() > 1)
+ {
+ return 0;
+ }
+
+ iValue = 0;
+
+ if (GC.getGameINLINE().isOption(GAMEOPTION_ALWAYS_PEACE))
+ {
+ iValue += 4;
+ }
+
+ for (int iI = 0; iI < GC.getNumTraitInfos(); iI++)
+ {
+ if (hasTrait((TraitTypes)iI))
+ {
+ // spiritual +4
+ iValue += ((GC.getTraitInfo((TraitTypes)iI).getMaxAnarchy() == 0) ? 4 : 0);
+
+ // creative +4
+ iValue += (GC.getTraitInfo((TraitTypes)iI).getCommerceChange(COMMERCE_CULTURE) * 2);
+
+ // (none in default xml), set so 25% boost = 4
+ iValue += (GC.getTraitInfo((TraitTypes)iI).getCommerceModifier(COMMERCE_CULTURE) / 6);
+
+ // philisophical +4
+ iValue += (GC.getTraitInfo((TraitTypes)iI).getGreatPeopleRateModifier() / 25);
+
+ // financial +4
+ iValue += (GC.getTraitInfo((TraitTypes)iI).getExtraYieldThreshold(YIELD_COMMERCE)) * 2 * GC.getDefineINT("EXTRA_YIELD");
+
+ // (none in default xml), set so 100% boost = 4
+ iValue += (GC.getTraitInfo((TraitTypes)iI).getTradeYieldModifier(YIELD_COMMERCE)) / 25;
+
+ // industrious +4
+ iValue += ((GC.getTraitInfo((TraitTypes)iI).getMaxGlobalBuildingProductionModifier() / 25));
+ }
+ }
+
+ iValue += (GC.getGameINLINE().isOption(GAMEOPTION_AGGRESSIVE_AI) ? -3 : 0);
+
+ CivicTypes eCivic = (CivicTypes)GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivic();
+ if ((eCivic != NO_CIVIC) && (GC.getCivicInfo(eCivic).isNoNonStateReligionSpread()))
+ {
+ iValue -= 3;
+ }
+
+ iValue += countHolyCities();
+ if ((GET_TEAM(getTeam()).isAVassal()) && (getNumCities() > 5))
+ {
+ int iReligionCount = countTotalHasReligion();
+ if (((iReligionCount * 100) / getNumCities()) > 250)
+ {
+ iValue += 1;
+ iValue += ((2 * iReligionCount) + 1) / getNumCities();
+ }
+ }
+
+ //atleast I'm honest
+ int iNonsense = 0;
+ iNonsense += getCapitalCity()->getX();
+ iNonsense += getCapitalCity()->getY();
+
+ iValue += (iNonsense % 7);
+
+ if (iValue < 10)
+ {
+ return 0;
+ }
+
+ if (getCurrentEra() >= (GC.getNumEraInfos() - (2 + iNonsense % 2)))
+ {
+ if (countTotalHasReligion() >= getNumCities() * 3)
+ {
+ return 3;
+ }
+
+ int iHighCultureCount = 0;
+
+ int iLoop;
+ CvCity* pLoopCity;
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ // is culture rate over 100?
+ if (pLoopCity->getBaseCommerceRate(COMMERCE_CULTURE) > 100)
+ {
+ iHighCultureCount++;
+ }
+ // or is the culture level 1 less than required to win?
+ else if (pLoopCity->getCultureLevel() >= (GC.getGameINLINE().culturalVictoryCultureLevel() - 1))
+ {
+ iHighCultureCount++;
+ }
+ }
+
+ // if we have enough high culture cities, go to stage 3
+ if (iHighCultureCount >= GC.getGameINLINE().culturalVictoryNumCultureCities())
+ {
+ return 3;
+ }
+ }
+
+ if (getCurrentEra() >= ((GC.getNumEraInfos() / 3) + iNonsense % 2))
+ {
+ return 2;
+ }
+ else
+ {
+ return 1;
+ }
+ FAssert(false);
+}
+
+
+bool CvPlayerAI::AI_isDoStrategy(int iStrategy) const
+{
+ if (isHuman())
+ {
+ return false;
+ }
+ return (iStrategy & AI_getStrategyHash());
+}
+
+void CvPlayerAI::AI_forceUpdateStrategies()
+{
+ //this forces a recache.
+ m_iStrategyHashCacheTurn = -1;
+}
+
+int CvPlayerAI::AI_getStrategyHash() const
+{
+ if ((m_iStrategyHash != 0) && (m_iStrategyHashCacheTurn == GC.getGameINLINE().getGameTurn()))
+ {
+ return m_iStrategyHash;
+ }
+
+ const FlavorTypes AI_FLAVOR_MILITARY = (FlavorTypes)0;
+ const FlavorTypes AI_FLAVOR_RELIGION = (FlavorTypes)1;
+ const FlavorTypes AI_FLAVOR_PRODUCTION = (FlavorTypes)2;
+ const FlavorTypes AI_FLAVOR_GOLD = (FlavorTypes)3;
+ const FlavorTypes AI_FLAVOR_SCIENCE = (FlavorTypes)4;
+ const FlavorTypes AI_FLAVOR_CULTURE = (FlavorTypes)5;
+ const FlavorTypes AI_FLAVOR_GROWTH = (FlavorTypes)6;
+
+ int iI, iJ, iK;
+ UnitTypes eLoopUnit;
+
+ m_iStrategyHash = AI_DEFAULT_STRATEGY;
+ m_iStrategyHashCacheTurn = GC.getGameINLINE().getGameTurn();
+
+ if (AI_getFlavorValue(AI_FLAVOR_PRODUCTION) >= 2) // 0, 2, 5 or 10 in default xml [augustus 5, frederick 10, huayna 2, jc 2, chinese leader 2, qin 5, ramsess 2, roosevelt 5, stalin 2]
+ {
+ m_iStrategyHash |= AI_STRATEGY_PRODUCTION;
+ }
+
+ if (getCapitalCity() == NULL)
+ {
+ return m_iStrategyHash;
+ }
+
+ int iNonsense = 0;
+ iNonsense += getCapitalCity()->getX();
+ iNonsense += getCapitalCity()->getY();
+
+ int iCurrentEra = getCurrentEra();
+ int iMetCount = GET_TEAM(getTeam()).getHasMetCivCount(true);
+ int iParanoia = 0;
+
+ //peace
+ if (iMetCount == 0)
+ {
+ iParanoia = 0;
+ }
+ else
+ {
+ for (iI = 0; iI < MAX_PLAYERS; iI++)
+ {
+ if ((iI != getID()) && GET_PLAYER((PlayerTypes)iI).isAlive())
+ {
+ if (!GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isAVassal())
+ {
+ int iCloseness = AI_playerCloseness((PlayerTypes)iI, 5 + iCurrentEra);
+ if (iCloseness > 0)
+ {
+ int iWarMemory = GET_PLAYER((PlayerTypes)iI).AI_getMemoryAttitude(getID(), MEMORY_DECLARED_WAR);
+ if (iWarMemory > 0)
+ {
+ //they are a snake
+ iParanoia += 50 + 20 * iWarMemory;
+ break;
+ }
+
+ if (AI_getAttitude((PlayerTypes)iI) < ATTITUDE_PLEASED)
+ {
+ iParanoia += 30;
+ }
+
+ //perform some personality profiling
+ for (iJ = 0; iJ < MAX_PLAYERS; iJ++)
+ {
+ //XXX the alive check means it doesn't count murder victims, should it?
+ if ((iJ != getID()) && (iI != iJ) && GET_PLAYER((PlayerTypes)iJ).isAlive()
+ && GET_TEAM(getTeam()).isHasMet((TeamTypes)iJ) && !GET_TEAM(GET_PLAYER((PlayerTypes)iJ).getTeam()).isAVassal())
+ {
+ if (GET_PLAYER((PlayerTypes)iI).AI_getMemoryAttitude((PlayerTypes)iJ, MEMORY_DECLARED_WAR) > 0)
+ {
+ //Do we not hate the victim?
+ if (AI_getAttitude((PlayerTypes)iJ) >= ATTITUDE_ANNOYED)
+ {
+ iParanoia += (iCloseness < 15) ? 60 : 100;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ iParanoia -= iCurrentEra * 10;
+
+ if (iParanoia < ((iMetCount > 1) ? 100 : 50))
+ {
+ m_iStrategyHash |= AI_STRATEGY_PEACE;
+ }
+
+ //Unit Analysis
+ int iBestSlowUnitCombat = -1;
+ int iBestFastUnitCombat = -1;
+
+ bool bHasMobileArtillery = false;
+ bool bHasMobileAntiair = false;
+ bool bHasBomber = false;
+
+ int iNukeCount = 0;
+
+ int iAttackUnitCount = 0;
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ eLoopUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI)));
+
+ if (NO_UNIT != eLoopUnit)
+ {
+ if (getCapitalCity() != NULL)
+ {
+ if (getCapitalCity()->canTrain(eLoopUnit))
+ {
+ CvUnitInfo& kLoopUnit = GC.getUnitInfo(eLoopUnit);
+ bool bIsUU = (GC.getUnitClassInfo((UnitClassTypes)iI).getDefaultUnitIndex()) != (GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI));
+ if (kLoopUnit.getUnitAIType(UNITAI_RESERVE) || kLoopUnit.getUnitAIType(UNITAI_ATTACK_CITY)
+ || kLoopUnit.getUnitAIType(UNITAI_COUNTER) || kLoopUnit.getUnitAIType(UNITAI_PILLAGE))
+ {
+
+ iAttackUnitCount++;
+
+ //UU love
+ if (bIsUU)
+ {
+ if (kLoopUnit.getUnitAIType(UNITAI_ATTACK_CITY)
+ || (kLoopUnit.getUnitAIType(UNITAI_ATTACK) && !kLoopUnit.getUnitAIType(UNITAI_CITY_DEFENSE)))
+ {
+ iAttackUnitCount++;
+ }
+ }
+ int iCombat = kLoopUnit.getCombat();
+ int iMoves = kLoopUnit.getMoves();
+ if (iMoves == 1)
+ {
+ iBestSlowUnitCombat = std::max(iBestSlowUnitCombat, iCombat);
+ }
+ else if (iMoves > 1)
+ {
+ iBestFastUnitCombat = std::max(iBestFastUnitCombat, iCombat);
+ if (bIsUU)
+ {
+ iBestFastUnitCombat += 1;
+ }
+ }
+ }
+ if (kLoopUnit.getMoves() > 1)
+ {
+ if (kLoopUnit.getInterceptionProbability() > 25)
+ {
+ bHasMobileAntiair = true;
+ }
+ if (kLoopUnit.getBombardRate() > 10)
+ {
+ bHasMobileArtillery = true;
+ }
+ }
+ if (kLoopUnit.getAirRange() > 1)
+ {
+ if (!kLoopUnit.isSuicide())
+ {
+ if ((kLoopUnit.getBombRate() > 5) && (kLoopUnit.getAirCombat() > 0))
+ {
+ bHasBomber = true;
+ }
+ }
+ }
+
+ if (kLoopUnit.getNukeRange() > 0)
+ {
+ iNukeCount++;
+ }
+ }
+ }
+ }
+ }
+
+ if (iAttackUnitCount <= 1)
+ {
+ m_iStrategyHash |= AI_STRATEGY_GET_BETTER_UNITS;
+ }
+ if (iBestFastUnitCombat > iBestSlowUnitCombat)
+ {
+ m_iStrategyHash |= AI_STRATEGY_FASTMOVERS;
+ if (bHasMobileArtillery && bHasMobileAntiair)
+ {
+ m_iStrategyHash |= AI_STRATEGY_LAND_BLITZ;
+ }
+ }
+ if (iNukeCount > 0)
+ {
+ if ((GC.getLeaderHeadInfo(getPersonalityType()).getBuildUnitProb() + iNonsense % 15) >= (GC.getGameINLINE().isOption(GAMEOPTION_AGGRESSIVE_AI) ? 37 : 43))
+ {
+ m_iStrategyHash |= AI_STRATEGY_OWABWNW;
+ }
+ }
+ if (bHasBomber)
+ {
+ if (!(m_iStrategyHash & AI_STRATEGY_LAND_BLITZ))
+ {
+ m_iStrategyHash |= AI_STRATEGY_AIR_BLITZ;
+ }
+ else
+ {
+ if ((iNonsense % 2) == 0)
+ {
+ m_iStrategyHash |= AI_STRATEGY_AIR_BLITZ;
+ m_iStrategyHash &= ~AI_STRATEGY_LAND_BLITZ;
+ }
+ }
+ }
+
+ //missionary
+ {
+ if (getStateReligion() != NO_RELIGION)
+ {
+ int iHolyCityCount = countHolyCities();
+ if ((iHolyCityCount > 0) && hasHolyCity(getStateReligion()))
+ {
+ int iMissionary = 0;
+ //Missionary
+ iMissionary += AI_getFlavorValue(AI_FLAVOR_GROWTH) * 2; // up to 10
+ iMissionary += AI_getFlavorValue(AI_FLAVOR_CULTURE) * 4; // up to 40
+ iMissionary += AI_getFlavorValue(AI_FLAVOR_RELIGION) * 6; // up to 60
+
+ CivicTypes eCivic = (CivicTypes)GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivic();
+ if ((eCivic != NO_CIVIC) && (GC.getCivicInfo(eCivic).isNoNonStateReligionSpread()))
+ {
+ iMissionary += 20;
+ }
+
+ iMissionary += (iHolyCityCount - 1) * 5;
+
+ iMissionary += iMetCount * 7;
+
+ for (iI = 0; iI < MAX_PLAYERS; iI++)
+ {
+ if (GET_PLAYER((PlayerTypes)iI).isAlive())
+ {
+ if (iI != getID())
+ {
+ if (GET_TEAM(getTeam()).isOpenBorders(GET_PLAYER((PlayerTypes)iI).getTeam()))
+ {
+ iMissionary += (GET_PLAYER((PlayerTypes)iI).countHolyCities() == 0) ? 12 : 4;
+ }
+ if ((GET_PLAYER((PlayerTypes)iI).getStateReligion() == getStateReligion()))
+ {
+ iMissionary += 10;
+ }
+ }
+ }
+ }
+
+ iMissionary += (iNonsense % 7) * 3;
+
+ if (iMissionary > 100)
+ {
+ m_iStrategyHash |= AI_STRATEGY_MISSIONARY;
+ }
+ }
+ }
+ }
+
+ //dagger
+ if (!(m_iStrategyHash & AI_STRATEGY_MISSIONARY)
+ && ((iCurrentEra <= (2+(iNonsense%2)) && (iMetCount > 0)) && (iParanoia > 0)))
+ {
+ int iDagger = 0;
+ iDagger += 12000 / std::max(100, (50 + GC.getLeaderHeadInfo(getPersonalityType()).getMaxWarRand()));
+ iDagger *= (iNonsense % 11);
+ iDagger /= 10;
+ iDagger += 5 * std::min(8, AI_getFlavorValue(AI_FLAVOR_MILITARY));
+
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ eLoopUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI)));
+
+ if ((eLoopUnit != NO_UNIT) && (GC.getUnitInfo(eLoopUnit).getCombat() > 0))
+ {
+ if ((GC.getUnitClassInfo((UnitClassTypes)iI).getDefaultUnitIndex()) != (GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI)))
+ {
+ bool bIsDefensive = (GC.getUnitInfo(eLoopUnit).getUnitAIType(UNITAI_CITY_DEFENSE) &&
+ !GC.getUnitInfo(eLoopUnit).getUnitAIType(UNITAI_RESERVE));
+
+ iDagger += bIsDefensive ? -10 : 0;
+
+ if (getCapitalCity()->canTrain(eLoopUnit))
+ {
+ iDagger += bIsDefensive ? 10 : 40;
+
+ int iUUStr = GC.getUnitInfo(eLoopUnit).getCombat();
+ int iNormalStr = GC.getUnitInfo((UnitTypes)(GC.getUnitClassInfo((UnitClassTypes)iI).getDefaultUnitIndex())).getCombat();
+ iDagger += 20 * range((iUUStr - iNormalStr), 0, 2);
+ if (GC.getUnitInfo(eLoopUnit).getPrereqAndTech() == NO_TECH)
+ {
+ iDagger += 20;
+ }
+ }
+ else
+ {
+ if (GC.getUnitInfo(eLoopUnit).getPrereqAndTech() != NO_TECH)
+ {
+ if (GC.getTechInfo((TechTypes)(GC.getUnitInfo(eLoopUnit).getPrereqAndTech())).getEra() <= (iCurrentEra + 1))
+ {
+ if (GET_TEAM(getTeam()).isHasTech((TechTypes)GC.getUnitInfo(eLoopUnit).getPrereqAndTech()))
+ {
+ //we have the tech but can't train the unit, dejection.
+ iDagger += 10;
+ }
+ else
+ {
+ //we don't have the tech, it's understandable we can't train.
+ iDagger += 30;
+ }
+ }
+ }
+
+ bool bNeedsAndBonus = false;
+ int iOrBonusCount = 0;
+ int iOrBonusHave = 0;
+
+ for (iJ = 0; iJ < GC.getNumBonusInfos(); iJ++)
+ {
+ BonusTypes eBonus = (BonusTypes)iJ;
+ if (eBonus != NO_BONUS)
+ {
+ if (GC.getUnitInfo(eLoopUnit).getPrereqAndBonus() == eBonus)
+ {
+ if (getNumTradeableBonuses(eBonus) == 0)
+ {
+ bNeedsAndBonus = true;
+ }
+ }
+
+ for (iK = 0; iK < GC.getNUM_UNIT_PREREQ_OR_BONUSES(); iK++)
+ {
+ if (GC.getUnitInfo(eLoopUnit).getPrereqOrBonuses(iK) == eBonus)
+ {
+ iOrBonusCount++;
+ if (getNumTradeableBonuses(eBonus) > 0)
+ {
+ iOrBonusHave++;
+ }
+ }
+ }
+ }
+ }
+
+
+ iDagger += 20;
+ if (bNeedsAndBonus)
+ {
+ iDagger -= 20;
+ }
+ if ((iOrBonusCount > 0) && (iOrBonusHave == 0))
+ {
+ iDagger -= 20;
+ }
+ }
+ }
+ }
+ }
+
+ if (!GC.getGameINLINE().isOption(GAMEOPTION_AGGRESSIVE_AI))
+ {
+ iDagger += range(100 - GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAITrainPercent(), 0, 15);
+ }
+
+ if ((getCapitalCity()->area()->getAreaAIType(getTeam()) == AREAAI_OFFENSIVE) || (getCapitalCity()->area()->getAreaAIType(getTeam()) == AREAAI_DEFENSIVE))
+ {
+ iDagger += (iAttackUnitCount > 0) ? 40 : 20;
+ }
+
+ if (iDagger >= AI_DAGGER_THRESHOLD)
+ {
+ m_iStrategyHash |= AI_STRATEGY_DAGGER;
+ }
+ }
+
+ int iCultureStage = AI_getCultureVictoryStage();
+ if (iCultureStage > 0)
+ {
+ m_iStrategyHash |= AI_STRATEGY_CULTURE1;
+ if (iCultureStage > 1)
+ {
+ m_iStrategyHash |= AI_STRATEGY_CULTURE2;
+ if (iCultureStage > 2)
+ {
+ m_iStrategyHash |= AI_STRATEGY_CULTURE3;
+ if (AI_cultureVictoryTechValue(getCurrentResearch()) < 100)
+ {
+ m_iStrategyHash |= AI_STRATEGY_CULTURE4;
+ }
+ }
+ }
+ }
+
+ // turn off dagger if culture gets to 2
+ if (m_iStrategyHash & AI_STRATEGY_CULTURE2)
+ {
+ m_iStrategyHash &= ~AI_STRATEGY_DAGGER;
+ }
+
+
+ {//Crush
+ int iWarCount = 0;
+ int iCrushValue = 0;
+
+ iCrushValue += (iNonsense % 4);
+
+ if (m_iStrategyHash & AI_STRATEGY_DAGGER)
+ {
+ iCrushValue += 3;
+ }
+ if (GC.getGameINLINE().isOption(GAMEOPTION_AGGRESSIVE_AI))
+ {
+ iCrushValue += 3;
+ }
+
+ for (iI = 0; iI < MAX_CIV_TEAMS; iI++)
+ {
+ if ((GET_TEAM((TeamTypes)iI).isAlive()) && (iI != getID()))
+ {
+ if (GET_TEAM(getTeam()).AI_getWarPlan((TeamTypes)iI) != NO_WARPLAN)
+ {
+ if (!GET_TEAM((TeamTypes)iI).isAVassal())
+ {
+ if (GET_TEAM(getTeam()).AI_teamCloseness((TeamTypes)iI) > 0)
+ {
+ iWarCount++;
+ }
+ }
+
+ if (GET_TEAM(getTeam()).AI_getWarPlan((TeamTypes)iI) == WARPLAN_PREPARING_TOTAL)
+ {
+ iCrushValue += 6;
+ }
+ else if ((GET_TEAM(getTeam()).AI_getWarPlan((TeamTypes)iI) == WARPLAN_TOTAL) && (GET_TEAM(getTeam()).AI_getWarPlanStateCounter((TeamTypes)iI) < 20))
+ {
+ iCrushValue += 6;
+ }
+
+ if ((GET_TEAM(getTeam()).AI_getWarPlan((TeamTypes)iI) == WARPLAN_DOGPILE) && (GET_TEAM(getTeam()).AI_getWarPlanStateCounter((TeamTypes)iI) < 20))
+ {
+ for (iJ = 0; iJ < MAX_TEAMS; iJ++)
+ {
+ if ((iJ != iI) && iJ != getID())
+ {
+ if ((atWar((TeamTypes)iI, (TeamTypes)iJ)) && !GET_TEAM((TeamTypes)iI).isAVassal())
+ {
+ iCrushValue += 4;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if ((iWarCount <= 1) && (iCrushValue >= 10))
+ {
+ m_iStrategyHash |= AI_STRATEGY_CRUSH;
+ }
+ }
+
+ {
+ CvTeamAI& kTeam = GET_TEAM(getTeam());
+ int iOurVictoryCountdown = kTeam.AI_getLowestVictoryCountdown();
+
+ int iTheirVictoryCountdown = MAX_INT;
+
+ for (iI = 0; iI < MAX_CIV_TEAMS; iI++)
+ {
+ if ((GET_TEAM((TeamTypes)iI).isAlive()) && (iI != getID()))
+ {
+ CvTeamAI& kOtherTeam = GET_TEAM((TeamTypes)iI);
+ iTheirVictoryCountdown = std::min(iTheirVictoryCountdown, kOtherTeam.AI_getLowestVictoryCountdown());
+ }
+ }
+
+ if (MAX_INT == iTheirVictoryCountdown)
+ {
+ iTheirVictoryCountdown = -1;
+ }
+
+ if ((iOurVictoryCountdown >= 0) && (iOurVictoryCountdown <= iTheirVictoryCountdown))
+ {
+ m_iStrategyHash |= AI_STRATEGY_LAST_STAND;
+ }
+ if ((iTheirVictoryCountdown > 0) && (iTheirVictoryCountdown < iOurVictoryCountdown))
+ {
+ m_iStrategyHash |= AI_STRATEGY_FINAL_WAR;
+ }
+
+ if (iOurVictoryCountdown < 0)
+ {
+ if (isCurrentResearchRepeat())
+ {
+ int iStronger = 0;
+ int iAlive = 1;
+ for (int iTeam = 0; iTeam < MAX_CIV_TEAMS; iTeam++)
+ {
+ if (iTeam != getTeam())
+ {
+ CvTeamAI& kLoopTeam = GET_TEAM((TeamTypes)iTeam);
+ if (kLoopTeam.isAlive())
+ {
+ iAlive++;
+ if (kTeam.getPower(true) < kLoopTeam.getPower(true))
+ {
+ iStronger++;
+ }
+ }
+ }
+ }
+
+ if ((iStronger <= 1) || (iStronger <= iAlive / 4))
+ {
+ m_iStrategyHash |= AI_STRATEGY_FINAL_WAR;
+ }
+ }
+ }
+
+ }
+
+ if (isCurrentResearchRepeat())
+ {
+ int iTotalVictories = 0;
+ int iAchieveVictories = 0;
+ int iWarVictories = 0;
+
+
+ int iThreshold = std::max(1, (GC.getGame().countCivTeamsAlive() + 1) / 4);
+
+ CvTeamAI& kTeam = GET_TEAM(getTeam());
+ for (int iVictory = 0; iVictory < GC.getNumVictoryInfos(); iVictory++)
+ {
+ CvVictoryInfo& kVictory = GC.getVictoryInfo((VictoryTypes)iVictory);
+ if (GC.getGame().isVictoryValid((VictoryTypes)iVictory))
+ {
+ iTotalVictories ++;
+ if (kVictory.isDiploVote())
+ {
+ //
+ }
+ else if (kVictory.isEndScore())
+ {
+ int iHigherCount = 0;
+ int IWeakerCount = 0;
+ for (int iTeam = 0; iTeam < MAX_CIV_TEAMS; iTeam++)
+ {
+ if (iTeam != getTeam())
+ {
+ CvTeamAI& kLoopTeam = GET_TEAM((TeamTypes)iTeam);
+ if (kLoopTeam.isAlive())
+ {
+ if (GC.getGame().getTeamScore(getTeam()) < ((GC.getGame().getTeamScore((TeamTypes)iTeam) * 90) / 100))
+ {
+ iHigherCount++;
+ if (kTeam.getPower(true) > kLoopTeam.getPower(true))
+ {
+ IWeakerCount++;
+ }
+ }
+ }
+ }
+ }
+
+ if (iHigherCount > 0)
+ {
+ if (IWeakerCount == iHigherCount)
+ {
+ iWarVictories++;
+ }
+ }
+ }
+ else if (kVictory.getCityCulture() > 0)
+ {
+ if (m_iStrategyHash & AI_STRATEGY_CULTURE1)
+ {
+ iAchieveVictories++;
+ }
+ }
+ else if (kVictory.getMinLandPercent() > 0 || kVictory.getLandPercent() > 0)
+ {
+ int iLargerCount = 0;
+ for (int iTeam = 0; iTeam < MAX_CIV_TEAMS; iTeam++)
+ {
+ if (iTeam != getTeam())
+ {
+ CvTeamAI& kLoopTeam = GET_TEAM((TeamTypes)iTeam);
+ if (kLoopTeam.isAlive())
+ {
+ if (kTeam.getTotalLand(true) < kLoopTeam.getTotalLand(true))
+ {
+ iLargerCount++;
+ }
+ }
+ }
+ }
+ if (iLargerCount <= iThreshold)
+ {
+ iWarVictories++;
+ }
+ }
+ else if (kVictory.isConquest())
+ {
+ int iStrongerCount = 0;
+ for (int iTeam = 0; iTeam < MAX_CIV_TEAMS; iTeam++)
+ {
+ if (iTeam != getTeam())
+ {
+ CvTeamAI& kLoopTeam = GET_TEAM((TeamTypes)iTeam);
+ if (kLoopTeam.isAlive())
+ {
+ if (kTeam.getPower(true) < kLoopTeam.getPower(true))
+ {
+ iStrongerCount++;
+ }
+ }
+ }
+ }
+ if (iStrongerCount <= iThreshold)
+ {
+ iWarVictories++;
+ }
+ }
+ else
+ {
+ if (kTeam.getVictoryCountdown((VictoryTypes)iVictory) > 0)
+ {
+ iAchieveVictories++;
+ }
+ }
+ }
+ }
+
+ if (iAchieveVictories == 0)
+ {
+ if (iWarVictories > 0)
+ {
+ m_iStrategyHash |= AI_STRATEGY_FINAL_WAR;
+ }
+ }
+ }
+
+ // Espionage
+ if (!GC.getGameINLINE().isOption(GAMEOPTION_NO_ESPIONAGE))
+ {
+ int iTempValue = 0;
+ if (getCommercePercent(COMMERCE_ESPIONAGE) == 0)
+ {
+ iTempValue += 4;
+ }
+
+ if (GET_TEAM(getTeam()).getAnyWarPlanCount(true) == 0)
+ {
+ iTempValue += 3;
+ }
+
+ iTempValue += (100 - AI_getEspionageWeight()) / 10;
+
+ iTempValue += iNonsense % 12;
+
+ if (iTempValue > 10)
+ {
+ m_iStrategyHash |= AI_STRATEGY_BIG_ESPIONAGE;
+ }
+ }
+ //Turn off inappropriate strategies.
+ if (GC.getGameINLINE().isOption(GAMEOPTION_ALWAYS_PEACE))
+ {
+ m_iStrategyHash &= ~AI_STRATEGY_DAGGER;
+ m_iStrategyHash &= ~AI_STRATEGY_CRUSH;
+ m_iStrategyHash &= ~AI_STRATEGY_OWABWNW;
+ m_iStrategyHash &= ~AI_STRATEGY_FASTMOVERS;
+ m_iStrategyHash &= ~AI_STRATEGY_FINAL_WAR;
+ }
+
+ return m_iStrategyHash;
+}
+
+
+void CvPlayerAI::AI_nowHasTech(TechTypes eTech)
+{
+ // while its _possible_ to do checks, for financial trouble, and this tech adds financial buildings
+ // if in war and this tech adds important war units
+ // etc
+ // it makes more sense to just redetermine what to produce
+ // that is already done every time a civ meets a new civ, it makes sense to do it when a new tech is learned
+ // if this is changed, then at a minimum, AI_isFinancialTrouble should be checked
+ if (!isHuman())
+ {
+ int iGameTurn = GC.getGameINLINE().getGameTurn();
+
+ // only reset at most every 10 turns
+ if (iGameTurn > m_iTurnLastProductionDirty + 10)
+ {
+ // redeterimine the best things to build in each city
+ AI_makeProductionDirty();
+
+ m_iTurnLastProductionDirty = iGameTurn;
+ }
+ }
+
+}
+
+
+int CvPlayerAI::AI_countDeadlockedBonuses(CvPlot* pPlot) const
+{
+ CvPlot* pLoopPlot;
+ CvPlot* pLoopPlot2;
+ int iDX, iDY;
+ int iI;
+
+ int iMinRange = GC.getMIN_CITY_RANGE();
+ int iRange = iMinRange * 2;
+ int iCount = 0;
+
+ for (iDX = -(iRange); iDX <= iRange; iDX++)
+ {
+ for (iDY = -(iRange); iDY <= iRange; iDY++)
+ {
+ if (plotDistance(iDX, iDY, 0, 0) > CITY_PLOTS_RADIUS)
+ {
+ pLoopPlot = plotXY(pPlot->getX_INLINE(), pPlot->getY_INLINE(), iDX, iDY);
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->getBonusType(getTeam()) != NO_BONUS)
+ {
+ if (!pLoopPlot->isCityRadius() && ((pLoopPlot->area() == pPlot->area()) || pLoopPlot->isWater()))
+ {
+ bool bCanFound = false;
+ bool bNeverFound = true;
+ //potentially blockable resource
+ //look for a city site within a city radius
+ for (iI = 0; iI < NUM_CITY_PLOTS; iI++)
+ {
+ pLoopPlot2 = plotCity(pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), iI);
+ if (pLoopPlot2 != NULL)
+ {
+ //canFound usually returns very quickly
+ if (canFound(pLoopPlot2->getX_INLINE(), pLoopPlot2->getY_INLINE(), false))
+ {
+ bNeverFound = false;
+ if (stepDistance(pPlot->getX_INLINE(), pPlot->getY_INLINE(), pLoopPlot2->getX_INLINE(), pLoopPlot2->getY_INLINE()) > iMinRange)
+ {
+ bCanFound = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!bNeverFound && !bCanFound)
+ {
+ iCount++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return iCount;
+}
+
+int CvPlayerAI::AI_getOurPlotStrength(CvPlot* pPlot, int iRange, bool bDefensiveBonuses, bool bTestMoves) const
+{
+ PROFILE_FUNC();
+
+ CLLNode* pUnitNode;
+ CvUnit* pLoopUnit;
+ CvPlot* pLoopPlot;
+ int iValue;
+ int iDistance;
+ int iDX, iDY;
+
+ iValue = 0;
+
+ for (iDX = -(iRange); iDX <= iRange; iDX++)
+ {
+ for (iDY = -(iRange); iDY <= iRange; iDY++)
+ {
+ pLoopPlot = plotXY(pPlot->getX_INLINE(), pPlot->getY_INLINE(), iDX, iDY);
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->area() == pPlot->area())
+ {
+ iDistance = stepDistance(pPlot->getX_INLINE(), pPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE());
+ pUnitNode = pLoopPlot->headUnitNode();
+
+ while (pUnitNode != NULL)
+ {
+ pLoopUnit = ::getUnit(pUnitNode->m_data);
+ pUnitNode = pLoopPlot->nextUnitNode(pUnitNode);
+
+ if (pLoopUnit->getOwnerINLINE() == getID())
+ {
+ if ((bDefensiveBonuses && pLoopUnit->canDefend()) || pLoopUnit->canAttack())
+ {
+ if (!(pLoopUnit->isInvisible(getTeam(), false)))
+ {
+ if (pLoopUnit->atPlot(pPlot) || pLoopUnit->canMoveInto(pPlot) || pLoopUnit->canMoveInto(pPlot, /*bAttack*/ true))
+ {
+ if (!bTestMoves)
+ {
+ iValue += pLoopUnit->currEffectiveStr((bDefensiveBonuses ? pPlot : NULL), NULL);
+ }
+ else
+ {
+ if (pLoopUnit->baseMoves() >= iDistance)
+ {
+ iValue += pLoopUnit->currEffectiveStr((bDefensiveBonuses ? pPlot : NULL), NULL);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ return iValue;
+}
+
+int CvPlayerAI::AI_getEnemyPlotStrength(CvPlot* pPlot, int iRange, bool bDefensiveBonuses, bool bTestMoves) const
+{
+ PROFILE_FUNC();
+
+ CLLNode* pUnitNode;
+ CvUnit* pLoopUnit;
+ CvPlot* pLoopPlot;
+ int iValue;
+ int iDistance;
+ int iDX, iDY;
+
+ iValue = 0;
+
+ for (iDX = -(iRange); iDX <= iRange; iDX++)
+ {
+ for (iDY = -(iRange); iDY <= iRange; iDY++)
+ {
+ pLoopPlot = plotXY(pPlot->getX_INLINE(), pPlot->getY_INLINE(), iDX, iDY);
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->area() == pPlot->area())
+ {
+ iDistance = stepDistance(pPlot->getX_INLINE(), pPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE());
+ pUnitNode = pLoopPlot->headUnitNode();
+
+ while (pUnitNode != NULL)
+ {
+ pLoopUnit = ::getUnit(pUnitNode->m_data);
+ pUnitNode = pLoopPlot->nextUnitNode(pUnitNode);
+
+ if (atWar(pLoopUnit->getTeam(), getTeam()))
+ {
+ if ((bDefensiveBonuses && pLoopUnit->canDefend()) || pLoopUnit->canAttack())
+ {
+ if (!(pLoopUnit->isInvisible(getTeam(), false)))
+ {
+ if (pPlot->isValidDomainForAction(*pLoopUnit))
+ {
+ if (!bTestMoves)
+ {
+ iValue += pLoopUnit->currEffectiveStr((bDefensiveBonuses ? pPlot : NULL), NULL);
+ }
+ else
+ {
+ int iDangerRange = pLoopUnit->baseMoves();
+ iDangerRange += ((pLoopPlot->isValidRoute(pLoopUnit)) ? 1 : 0);
+ if (iDangerRange >= iDistance)
+ {
+ iValue += pLoopUnit->currEffectiveStr((bDefensiveBonuses ? pPlot : NULL), NULL);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ return iValue;
+
+}
+
+int CvPlayerAI::AI_goldToUpgradeAllUnits(int iExpThreshold) const
+{
+ if (m_iUpgradeUnitsCacheTurn == GC.getGameINLINE().getGameTurn() && m_iUpgradeUnitsCachedExpThreshold == iExpThreshold)
+ {
+ return m_iUpgradeUnitsCachedGold;
+ }
+
+ int iTotalGold = 0;
+
+ CvCivilizationInfo& kCivilizationInfo = GC.getCivilizationInfo(getCivilizationType());
+
+ // cache the value for each unit type
+ std::vector aiUnitUpgradePrice(GC.getNumUnitInfos(), 0); // initializes to zeros
+
+ int iLoop;
+ for (CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
+ {
+ // if experience is below threshold, skip this unit
+ if (pLoopUnit->getExperience() < iExpThreshold)
+ {
+ continue;
+ }
+
+ UnitTypes eUnitType = pLoopUnit->getUnitType();
+
+ // check cached value for this unit type
+ int iCachedUnitGold = aiUnitUpgradePrice[eUnitType];
+ if (iCachedUnitGold != 0)
+ {
+ // if positive, add it to the sum
+ if (iCachedUnitGold > 0)
+ {
+ iTotalGold += iCachedUnitGold;
+ }
+
+ // either way, done with this unit
+ continue;
+ }
+
+ int iUnitGold = 0;
+ int iUnitUpgradePossibilities = 0;
+
+ UnitAITypes eUnitAIType = pLoopUnit->AI_getUnitAIType();
+ CvArea* pUnitArea = pLoopUnit->area();
+ int iUnitValue = AI_unitValue(eUnitType, eUnitAIType, pUnitArea);
+
+ for (int iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ UnitClassTypes eUpgradeUnitClassType = (UnitClassTypes) iI;
+ UnitTypes eUpgradeUnitType = (UnitTypes)(kCivilizationInfo.getCivilizationUnits(iI));
+
+ if (NO_UNIT != eUpgradeUnitType)
+ {
+ // is it better?
+ int iUpgradeValue = AI_unitValue(eUpgradeUnitType, eUnitAIType, pUnitArea);
+ if (iUpgradeValue > iUnitValue)
+ {
+ // is this a valid upgrade?
+ if (pLoopUnit->upgradeAvailable(eUnitType, eUpgradeUnitClassType))
+ {
+ // can we actually make this upgrade?
+ bool bCanUpgrade = false;
+ CvCity* pCapitalCity = getCapitalCity();
+ if (pCapitalCity != NULL && pCapitalCity->canTrain(eUpgradeUnitType))
+ {
+ bCanUpgrade = true;
+ }
+ else
+ {
+ CvCity* pCloseCity = GC.getMapINLINE().findCity(pLoopUnit->getX_INLINE(), pLoopUnit->getY_INLINE(), getID(), NO_TEAM, true, (pLoopUnit->getDomainType() == DOMAIN_SEA));
+ if (pCloseCity != NULL && pCloseCity->canTrain(eUpgradeUnitType))
+ {
+ bCanUpgrade = true;
+ }
+ }
+
+ if (bCanUpgrade)
+ {
+ iUnitGold += pLoopUnit->upgradePrice(eUpgradeUnitType);
+ iUnitUpgradePossibilities++;
+ }
+ }
+ }
+ }
+ }
+
+ // if we found any, find average and add to total
+ if (iUnitUpgradePossibilities > 0)
+ {
+ iUnitGold /= iUnitUpgradePossibilities;
+
+ // add to cache
+ aiUnitUpgradePrice[eUnitType] = iUnitGold;
+
+ // add to sum
+ iTotalGold += iUnitGold;
+ }
+ else
+ {
+ // add to cache, dont upgrade to this type
+ aiUnitUpgradePrice[eUnitType] = -1;
+ }
+ }
+
+ m_iUpgradeUnitsCacheTurn = GC.getGameINLINE().getGameTurn();
+ m_iUpgradeUnitsCachedExpThreshold = iExpThreshold;
+ m_iUpgradeUnitsCachedGold = iTotalGold;
+
+ return iTotalGold;
+}
+
+int CvPlayerAI::AI_goldTradeValuePercent() const
+{
+ int iValue = 2;
+ if (AI_isFinancialTrouble())
+ {
+ iValue += 1;
+ }
+ return 100 * iValue;
+
+}
+
+int CvPlayerAI::AI_averageYieldMultiplier(YieldTypes eYield) const
+{
+ FAssert(eYield > -1);
+ FAssert(eYield < NUM_YIELD_TYPES);
+
+ if (m_iAveragesCacheTurn != GC.getGameINLINE().getGameTurn())
+ {
+ AI_calculateAverages();
+ }
+
+ FAssert(m_aiAverageYieldMultiplier[eYield] > 0);
+ return m_aiAverageYieldMultiplier[eYield];
+}
+
+int CvPlayerAI::AI_averageCommerceMultiplier(CommerceTypes eCommerce) const
+{
+ FAssert(eCommerce > -1);
+ FAssert(eCommerce < NUM_COMMERCE_TYPES);
+
+ if (m_iAveragesCacheTurn != GC.getGameINLINE().getGameTurn())
+ {
+ AI_calculateAverages();
+ }
+
+ return m_aiAverageCommerceMultiplier[eCommerce];
+}
+
+int CvPlayerAI::AI_averageGreatPeopleMultiplier() const
+{
+ if (m_iAveragesCacheTurn != GC.getGameINLINE().getGameTurn())
+ {
+ AI_calculateAverages();
+ }
+ return m_iAverageGreatPeopleMultiplier;
+}
+
+//"100 eCommerce is worth (return) raw YIELD_COMMERCE
+int CvPlayerAI::AI_averageCommerceExchange(CommerceTypes eCommerce) const
+{
+ FAssert(eCommerce > -1);
+ FAssert(eCommerce < NUM_COMMERCE_TYPES);
+
+ if (m_iAveragesCacheTurn != GC.getGameINLINE().getGameTurn())
+ {
+ AI_calculateAverages();
+ }
+
+ return m_aiAverageCommerceExchange[eCommerce];
+}
+
+void CvPlayerAI::AI_calculateAverages() const
+{
+ CvCity* pLoopCity;
+ int iLoop;
+ int iI;
+
+ int iPopulation;
+ int iTotalPopulation;
+
+ for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
+ {
+ m_aiAverageYieldMultiplier[iI] = 0;
+ }
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
+ {
+ m_aiAverageCommerceMultiplier[iI] = 0;
+ }
+ m_iAverageGreatPeopleMultiplier = 0;
+
+ iTotalPopulation = 0;
+
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ iPopulation = std::max(pLoopCity->getPopulation(), NUM_CITY_PLOTS);
+ iTotalPopulation += iPopulation;
+
+ for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
+ {
+ m_aiAverageYieldMultiplier[iI] += iPopulation * pLoopCity->AI_yieldMultiplier((YieldTypes)iI);
+ }
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
+ {
+ m_aiAverageCommerceMultiplier[iI] += iPopulation * pLoopCity->getTotalCommerceRateModifier((CommerceTypes)iI);
+ }
+ m_iAverageGreatPeopleMultiplier += iPopulation * pLoopCity->getTotalGreatPeopleRateModifier();
+ }
+
+
+ if (iTotalPopulation > 0)
+ {
+ for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
+ {
+ m_aiAverageYieldMultiplier[iI] /= iTotalPopulation;
+ FAssert(m_aiAverageYieldMultiplier[iI] > 0);
+ }
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
+ {
+ m_aiAverageCommerceMultiplier[iI] /= iTotalPopulation;
+ FAssert(m_aiAverageCommerceMultiplier[iI] > 0);
+ }
+ m_iAverageGreatPeopleMultiplier /= iTotalPopulation;
+ FAssert(m_iAverageGreatPeopleMultiplier > 0);
+ }
+ else
+ {
+ for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
+ {
+ m_aiAverageYieldMultiplier[iI] = 100;
+ }
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
+ {
+ m_aiAverageCommerceMultiplier[iI] = 100;
+ }
+ m_iAverageGreatPeopleMultiplier = 100;
+ }
+
+
+ //Calculate Exchange Rate
+
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
+ {
+ m_aiAverageCommerceExchange[iI] = 0;
+ }
+
+ int iCommerce = 0;
+ int iTotalCommerce = 0;
+
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ iCommerce = pLoopCity->getYieldRate(YIELD_COMMERCE);
+ iTotalCommerce += iCommerce;
+
+ int iExtraCommerce = 0;
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
+ {
+ iExtraCommerce +=((pLoopCity->getSpecialistPopulation() + pLoopCity->getNumGreatPeople()) * getSpecialistExtraCommerce((CommerceTypes)iI));
+ iExtraCommerce += (pLoopCity->getBuildingCommerce((CommerceTypes)iI) + pLoopCity->getSpecialistCommerce((CommerceTypes)iI) + pLoopCity->getReligionCommerce((CommerceTypes)iI) + getFreeCityCommerce((CommerceTypes)iI));
+ }
+ iTotalCommerce += iExtraCommerce;
+
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
+ {
+ m_aiAverageCommerceExchange[iI] += ((iCommerce + iExtraCommerce) * pLoopCity->getTotalCommerceRateModifier((CommerceTypes)iI)) / 100;
+ }
+ }
+
+ for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
+ {
+ if (m_aiAverageCommerceExchange[iI] > 0)
+ {
+ m_aiAverageCommerceExchange[iI] = (100 * iTotalCommerce) / m_aiAverageCommerceExchange[iI];
+ }
+ else
+ {
+ m_aiAverageCommerceExchange[iI] = 100;
+ }
+ }
+
+ m_iAveragesCacheTurn = GC.getGameINLINE().getGameTurn();
+}
+
+void CvPlayerAI::AI_convertUnitAITypesForCrush()
+{
+ CvUnit* pLoopUnit;
+
+ int iLoop;
+
+ for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
+ {
+ bool bValid = false;
+ if ((pLoopUnit->AI_getUnitAIType() == UNITAI_RESERVE)
+ || (pLoopUnit->AI_isCityAIType() && (pLoopUnit->getExtraCityDefensePercent() <= 0)))
+ {
+ bValid = true;
+ }
+ if ((pLoopUnit->area()->getAreaAIType(getTeam()) == AREAAI_ASSAULT)
+ || (pLoopUnit->area()->getAreaAIType(getTeam()) == AREAAI_DEFENSIVE))
+ {
+ bValid = false;
+ }
+
+ if (!pLoopUnit->canAttack() || (pLoopUnit->AI_getUnitAIType() == UNITAI_CITY_SPECIAL))
+ {
+ bValid = false;
+ }
+
+ if (bValid)
+ {
+ if (pLoopUnit->plot()->isCity())
+ {
+ if (pLoopUnit->plot()->getPlotCity()->getOwner() == getID())
+ {
+ if (pLoopUnit->plot()->getBestDefender(getID()) == pLoopUnit)
+ {
+ bValid = false;
+ }
+ }
+ }
+ }
+
+ if (bValid)
+ {
+ pLoopUnit->AI_setUnitAIType(UNITAI_ATTACK_CITY);
+ }
+ }
+}
+
+int CvPlayerAI::AI_playerCloseness(PlayerTypes eIndex, int iMaxDistance) const
+{
+ PROFILE_FUNC();
+ FAssert(GET_PLAYER(eIndex).isAlive());
+ FAssert(eIndex != getID());
+
+ int iValue = 0;
+ int iLoop;
+ for (CvCity* pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ iValue += pLoopCity->AI_playerCloseness(eIndex, iMaxDistance);
+ }
+
+ return iValue;
+}
+
+
+int CvPlayerAI::AI_getTotalAreaCityThreat(CvArea* pArea) const
+{
+ PROFILE_FUNC();
+ CvCity* pLoopCity;
+ int iLoop;
+ int iValue;
+
+ iValue = 0;
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ if (pLoopCity->getArea() == pArea->getID())
+ {
+ iValue += pLoopCity->AI_cityThreat();
+ }
+ }
+ return iValue;
+}
+
+int CvPlayerAI::AI_countNumAreaHostileUnits(CvArea* pArea, bool bPlayer, bool bTeam, bool bNeutral, bool bHostile) const
+{
+ PROFILE_FUNC();
+ CvPlot* pLoopPlot;
+ int iCount;
+ int iI;
+
+ iCount = 0;
+
+ for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
+ {
+ pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
+ if ((pLoopPlot->area() == pArea) && pLoopPlot->isVisible(getTeam(), false) &&
+ ((bPlayer && pLoopPlot->getOwnerINLINE() == getID()) || (bTeam && pLoopPlot->getTeam() == getTeam())
+ || (bNeutral && !pLoopPlot->isOwned()) || (bHostile && pLoopPlot->isOwned() && GET_TEAM(getTeam()).isAtWar(pLoopPlot->getTeam()))))
+ {
+ iCount += pLoopPlot->plotCount(PUF_isEnemy, getID(), false, NO_PLAYER, NO_TEAM, PUF_isVisible, getID());
+ }
+ }
+ return iCount;
+}
+
+//this doesn't include the minimal one or two garrison units in each city.
+int CvPlayerAI::AI_getTotalFloatingDefendersNeeded(CvArea* pArea) const
+{
+ PROFILE_FUNC();
+ int iDefenders;
+ int iCurrentEra = getCurrentEra();
+ int iAreaCities = pArea->getCitiesPerPlayer(getID());
+
+ iCurrentEra = std::max(0, iCurrentEra - GC.getGame().getStartEra() / 2);
+
+ iDefenders = 1 + ((iCurrentEra + ((GC.getGameINLINE().getMaxCityElimination() > 0) ? 3 : 2)) * iAreaCities);
+ iDefenders /= 3;
+ iDefenders += pArea->getPopulationPerPlayer(getID()) / 7;
+
+ if (pArea->getAreaAIType(getTeam()) == AREAAI_DEFENSIVE)
+ {
+ iDefenders *= 2;
+ }
+ else if ((pArea->getAreaAIType(getTeam()) == AREAAI_OFFENSIVE) || (pArea->getAreaAIType(getTeam()) == AREAAI_MASSING))
+ {
+ iDefenders *= 2;
+ iDefenders /= 3;
+ }
+
+ if (AI_getTotalAreaCityThreat(pArea) == 0)
+ {
+ iDefenders /= 2;
+ }
+
+ if (!GC.getGameINLINE().isOption(GAMEOPTION_AGGRESSIVE_AI))
+ {
+ iDefenders *= 2;
+ iDefenders /= 3;
+ }
+
+ if (AI_isDoStrategy(AI_STRATEGY_GET_BETTER_UNITS) && (pArea->getAreaAIType(getTeam()) != AREAAI_DEFENSIVE))
+ {
+ iDefenders /= 2;
+ }
+
+ if (AI_isDoStrategy(AI_STRATEGY_CULTURE3))
+ {
+ iDefenders += 2 * iAreaCities;
+ if (pArea->getAreaAIType(getTeam()) == AREAAI_DEFENSIVE)
+ {
+ iDefenders *= 2; //go crazy
+ }
+ }
+
+ iDefenders *= 60;
+ iDefenders /= std::max(30, (GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAITrainPercent() - 20));
+
+ if ((iCurrentEra < 3) && (GC.getGameINLINE().isOption(GAMEOPTION_RAGING_BARBARIANS)))
+ {
+ iDefenders += 2;
+ }
+
+ if (getCapitalCity() != NULL)
+ {
+ if (getCapitalCity()->area() != pArea)
+ {
+ //Defend offshore islands only lightly.
+ iDefenders = std::min(iDefenders, iAreaCities * iAreaCities - 1);
+ }
+ }
+
+ return iDefenders;
+}
+
+int CvPlayerAI::AI_getTotalFloatingDefenders(CvArea* pArea) const
+{
+ PROFILE_FUNC();
+ int iCount = 0;
+
+ iCount += AI_totalAreaUnitAIs(pArea, UNITAI_COLLATERAL);
+ iCount += AI_totalAreaUnitAIs(pArea, UNITAI_RESERVE);
+ iCount += std::max(0, (AI_totalAreaUnitAIs(pArea, UNITAI_CITY_DEFENSE) - (pArea->getCitiesPerPlayer(getID()) * 2)));
+ iCount += AI_totalAreaUnitAIs(pArea, UNITAI_CITY_COUNTER);
+ iCount += AI_totalAreaUnitAIs(pArea, UNITAI_CITY_SPECIAL);
+ iCount += AI_totalAreaUnitAIs(pArea, UNITAI_DEFENSE_AIR);
+ return iCount;
+}
+
+RouteTypes CvPlayerAI::AI_bestAdvancedStartRoute(CvPlot* pPlot, int* piYieldValue) const
+{
+ RouteTypes eBestRoute = NO_ROUTE;
+ int iBestValue = -1;
+ for (int iI = 0; iI < GC.getNumRouteInfos(); iI++)
+ {
+ RouteTypes eRoute = (RouteTypes)iI;
+
+ int iValue = 0;
+ int iCost = getAdvancedStartRouteCost(eRoute, true, pPlot);
+
+ if (iCost >= 0)
+ {
+ iValue += GC.getRouteInfo(eRoute).getValue();
+
+ if (iValue > 0)
+ {
+ int iYieldValue = 0;
+ if (pPlot->getImprovementType() != NO_IMPROVEMENT)
+ {
+ iYieldValue += ((GC.getImprovementInfo(pPlot->getImprovementType()).getRouteYieldChanges(eRoute, YIELD_FOOD)) * 100);
+ iYieldValue += ((GC.getImprovementInfo(pPlot->getImprovementType()).getRouteYieldChanges(eRoute, YIELD_PRODUCTION)) * 60);
+ iYieldValue += ((GC.getImprovementInfo(pPlot->getImprovementType()).getRouteYieldChanges(eRoute, YIELD_COMMERCE)) * 40);
+ }
+ iValue *= 1000;
+ iValue /= (1 + iCost);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestRoute = eRoute;
+ if (piYieldValue != NULL)
+ {
+ *piYieldValue = iYieldValue;
+ }
+ }
+ }
+ }
+ }
+ return eBestRoute;
+}
+
+UnitTypes CvPlayerAI::AI_bestAdvancedStartUnitAI(CvPlot* pPlot, UnitAITypes eUnitAI) const
+{
+ UnitTypes eLoopUnit;
+ UnitTypes eBestUnit;
+ int iValue;
+ int iBestValue;
+ int iI, iJ, iK;
+
+ FAssertMsg(eUnitAI != NO_UNITAI, "UnitAI is not assigned a valid value");
+
+ iBestValue = 0;
+ eBestUnit = NO_UNIT;
+
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ eLoopUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI)));
+
+ if (eLoopUnit != NO_UNIT)
+ {
+ //if (!isHuman() || (GC.getUnitInfo(eLoopUnit).getDefaultUnitAIType() == eUnitAI))
+ {
+ int iUnitCost = getAdvancedStartUnitCost(eLoopUnit, true, pPlot);
+ if (iUnitCost >= 0)
+ {
+ iValue = AI_unitValue(eLoopUnit, eUnitAI, pPlot->area());
+
+ if (iValue > 0)
+ {
+ //free promotions. slow?
+ //only 1 promotion per source is counted (ie protective isn't counted twice)
+ int iPromotionValue = 0;
+
+ //special to the unit
+ for (iJ = 0; iJ < GC.getNumPromotionInfos(); iJ++)
+ {
+ if (GC.getUnitInfo(eLoopUnit).getFreePromotions(iJ))
+ {
+ iPromotionValue += 15;
+ break;
+ }
+ }
+
+ for (iK = 0; iK < GC.getNumPromotionInfos(); iK++)
+ {
+ if (isFreePromotion((UnitCombatTypes)GC.getUnitInfo(eLoopUnit).getUnitCombatType(), (PromotionTypes)iK))
+ {
+ iPromotionValue += 15;
+ break;
+ }
+
+ if (isFreePromotion((UnitClassTypes)GC.getUnitInfo(eLoopUnit).getUnitClassType(), (PromotionTypes)iK))
+ {
+ iPromotionValue += 15;
+ break;
+ }
+ }
+
+ //traits
+ for (iJ = 0; iJ < GC.getNumTraitInfos(); iJ++)
+ {
+ if (hasTrait((TraitTypes)iJ))
+ {
+ for (iK = 0; iK < GC.getNumPromotionInfos(); iK++)
+ {
+ if (GC.getTraitInfo((TraitTypes) iJ).isFreePromotion(iK))
+ {
+ if ((GC.getUnitInfo(eLoopUnit).getUnitCombatType() != NO_UNITCOMBAT) && GC.getTraitInfo((TraitTypes) iJ).isFreePromotionUnitCombat(GC.getUnitInfo(eLoopUnit).getUnitCombatType()))
+ {
+ iPromotionValue += 15;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ iValue *= (iPromotionValue + 100);
+ iValue /= 100;
+
+ iValue *= (GC.getGameINLINE().getSorenRandNum(40, "AI Best Advanced Start Unit") + 100);
+ iValue /= 100;
+
+ iValue *= (getNumCities() + 2);
+ iValue /= (getUnitClassCountPlusMaking((UnitClassTypes)iI) + getNumCities() + 2);
+
+ FAssert((MAX_INT / 1000) > iValue);
+ iValue *= 1000;
+
+ iValue /= 1 + iUnitCost;
+
+ iValue = std::max(1, iValue);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ eBestUnit = eLoopUnit;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return eBestUnit;
+}
+
+CvPlot* CvPlayerAI::AI_advancedStartFindCapitalPlot() const
+{
+ CvPlot* pBestPlot = NULL;
+ int iBestValue = -1;
+
+ for (int iPlayer = 0; iPlayer < MAX_PLAYERS; iPlayer++)
+ {
+ CvPlayer& kPlayer = GET_PLAYER((PlayerTypes)iPlayer);
+ if (kPlayer.isAlive())
+ {
+ if (kPlayer.getTeam() == getTeam())
+ {
+ CvPlot* pLoopPlot = kPlayer.getStartingPlot();
+ if (pLoopPlot != NULL)
+ {
+ if (getAdvancedStartCityCost(true, pLoopPlot) > 0)
+ {
+ int iX = pLoopPlot->getX_INLINE();
+ int iY = pLoopPlot->getY_INLINE();
+
+ int iValue = 1000;
+ if (iPlayer == getID())
+ {
+ iValue += 1000;
+ }
+ else
+ {
+ iValue += GC.getGame().getSorenRandNum(100, "AI Advanced Start Choose Team Start");
+ }
+ CvCity * pNearestCity = GC.getMapINLINE().findCity(iX, iY, NO_PLAYER, getTeam());
+ if (NULL != pNearestCity)
+ {
+ FAssert(pNearestCity->getTeam() == getTeam());
+ int iDistance = stepDistance(iX, iY, pNearestCity->getX_INLINE(), pNearestCity->getY_INLINE());
+ if (iDistance < 10)
+ {
+ iValue /= (10 - iDistance);
+ }
+ }
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ pBestPlot = pLoopPlot;
+ }
+ }
+ }
+ else
+ {
+ FAssertMsg(false, "StartingPlot for a live player is NULL!");
+ }
+ }
+ }
+ }
+
+ if (pBestPlot != NULL)
+ {
+ return pBestPlot;
+ }
+
+ FAssertMsg(false, "AS: Failed to find a starting plot for a player");
+
+ //Execution should almost never reach here.
+
+ //Update found values just in case - particulary important for simultaneous turns.
+ AI_updateFoundValues();
+
+ pBestPlot = NULL;
+ iBestValue = -1;
+
+ if (NULL != getStartingPlot())
+ {
+ for (int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
+ {
+ CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
+ if (pLoopPlot->getArea() == getStartingPlot()->getArea())
+ {
+ int iValue = pLoopPlot->getFoundValue(getID());
+ if (iValue > 0)
+ {
+ if (getAdvancedStartCityCost(true, pLoopPlot) > 0)
+ {
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ pBestPlot = pLoopPlot;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (pBestPlot != NULL)
+ {
+ return pBestPlot;
+ }
+
+ //Commence panic.
+ FAssertMsg(false, "Failed to find an advanced start starting plot");
+ return NULL;
+}
+
+
+bool CvPlayerAI::AI_advancedStartPlaceExploreUnits(bool bLand)
+{
+ CvPlot* pBestExplorePlot = NULL;
+ int iBestExploreValue = 0;
+ UnitTypes eBestUnitType = NO_UNIT;
+
+ UnitAITypes eUnitAI = NO_UNITAI;
+ if (bLand)
+ {
+ eUnitAI = UNITAI_EXPLORE;
+ }
+ else
+ {
+ eUnitAI = UNITAI_EXPLORE_SEA;
+ }
+
+ int iLoop;
+ CvCity* pLoopCity;
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ CvPlot* pLoopPlot = pLoopCity->plot();
+ CvArea* pLoopArea = bLand ? pLoopCity->area() : pLoopPlot->waterArea();
+
+ if (pLoopArea != NULL)
+ {
+ int iValue = std::max(0, pLoopArea->getNumUnrevealedTiles(getTeam()) - 10) * 10;
+ iValue += std::max(0, pLoopArea->getNumTiles() - 50);
+
+ if (iValue > 0)
+ {
+ int iOtherPlotCount = 0;
+ int iGoodyCount = 0;
+ int iExplorerCount = 0;
+ int iAreaId = pLoopArea->getID();
+
+ int iRange = 4;
+ for (int iX = -iRange; iX <= iRange; iX++)
+ {
+ for (int iY = -iRange; iY <= iRange; iY++)
+ {
+ CvPlot* pLoopPlot2 = plotXY(pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), iX, iY);
+ if (NULL != pLoopPlot2)
+ {
+ iExplorerCount += pLoopPlot2->plotCount(PUF_isUnitAIType, eUnitAI, -1, NO_PLAYER, getTeam());
+ if (pLoopPlot2->getArea() == iAreaId)
+ {
+ if (pLoopPlot2->isGoody())
+ {
+ iGoodyCount++;
+ }
+ if (pLoopPlot2->getTeam() != getTeam())
+ {
+ iOtherPlotCount++;
+ }
+ }
+ }
+ }
+ }
+
+ iValue -= 300 * iExplorerCount;
+ iValue += 200 * iGoodyCount;
+ iValue += 10 * iOtherPlotCount;
+ if (iValue > iBestExploreValue)
+ {
+ UnitTypes eUnit = AI_bestAdvancedStartUnitAI(pLoopPlot, eUnitAI);
+ if (eUnit != NO_UNIT)
+ {
+ eBestUnitType = eUnit;
+ iBestExploreValue = iValue;
+ pBestExplorePlot = pLoopPlot;
+ }
+ }
+ }
+ }
+ }
+
+ if (pBestExplorePlot != NULL)
+ {
+ doAdvancedStartAction(ADVANCEDSTARTACTION_UNIT, pBestExplorePlot->getX_INLINE(), pBestExplorePlot->getY_INLINE(), eBestUnitType, true);
+ return true;
+ }
+ return false;
+}
+
+void CvPlayerAI::AI_advancedStartRevealRadius(CvPlot* pPlot, int iRadius)
+{
+ for (int iRange = 1; iRange <=iRadius; iRange++)
+ {
+ for (int iX = -iRange; iX <= iRange; iX++)
+ {
+ for (int iY = -iRange; iY <= iRange; iY++)
+ {
+ if (plotDistance(0, 0, iX, iY) <= iRadius)
+ {
+ CvPlot* pLoopPlot = plotXY(pPlot->getX_INLINE(), pPlot->getY_INLINE(), iX, iY);
+
+ if (NULL != pLoopPlot)
+ {
+ if (getAdvancedStartVisibilityCost(true, pLoopPlot) > 0)
+ {
+ doAdvancedStartAction(ADVANCEDSTARTACTION_VISIBILITY, pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), -1, true);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+bool CvPlayerAI::AI_advancedStartPlaceCity(CvPlot* pPlot)
+{
+ //If there is already a city, then improve it.
+ CvCity* pCity = pPlot->getPlotCity();
+ if (pCity == NULL)
+ {
+ doAdvancedStartAction(ADVANCEDSTARTACTION_CITY, pPlot->getX(), pPlot->getY(), -1, true);
+
+ pCity = pPlot->getPlotCity();
+ if ((pCity == NULL) || (pCity->getOwnerINLINE() != getID()))
+ {
+ //this should never happen since the cost for a city should be 0 if
+ //the city can't be placed.
+ //(It can happen if another player has placed a city in the fog)
+ FAssertMsg(false, "ADVANCEDSTARTACTION_CITY failed in unexpected way");
+ return false;
+ }
+ }
+
+ if (pCity->getCultureLevel() <= 1)
+ {
+ doAdvancedStartAction(ADVANCEDSTARTACTION_CULTURE, pPlot->getX(), pPlot->getY(), -1, true);
+ }
+
+ //to account for culture expansion.
+ pCity->AI_updateBestBuild();
+
+ int iPlotsImproved = 0;
+ for (int iI = 0; iI < NUM_CITY_PLOTS; iI++)
+ {
+ if (iI != CITY_HOME_PLOT)
+ {
+ CvPlot* pLoopPlot = plotCity(pPlot->getX_INLINE(), pPlot->getY_INLINE(), iI);
+ if ((pLoopPlot != NULL) && (pLoopPlot->getWorkingCity() == pCity))
+ {
+ if (pLoopPlot->getImprovementType() != NO_IMPROVEMENT)
+ {
+ iPlotsImproved++;
+ }
+ }
+ }
+ }
+
+ int iTargetPopulation = pCity->happyLevel() + (getCurrentEra() / 2);
+
+ while (iPlotsImproved < iTargetPopulation)
+ {
+ CvPlot* pBestPlot;
+ ImprovementTypes eBestImprovement = NO_IMPROVEMENT;
+ int iBestValue = 0;
+ for (int iI = 0; iI < NUM_CITY_PLOTS; iI++)
+ {
+ int iValue = pCity->AI_getBestBuildValue(iI);
+ if (iValue > iBestValue)
+ {
+ BuildTypes eBuild = pCity->AI_getBestBuild(iI);
+ if (eBuild != NO_BUILD)
+ {
+ ImprovementTypes eImprovement = (ImprovementTypes)GC.getBuildInfo(eBuild).getImprovement();
+ if (eImprovement != NO_IMPROVEMENT)
+ {
+ CvPlot* pLoopPlot = plotCity(pCity->getX_INLINE(), pCity->getY_INLINE(), iI);
+ if ((pLoopPlot != NULL) && (pLoopPlot->getImprovementType() != eImprovement))
+ {
+ eBestImprovement = eImprovement;
+ pBestPlot = pLoopPlot;
+ iBestValue = iValue;
+ }
+ }
+ }
+ }
+ }
+
+ if (iBestValue > 0)
+ {
+
+ FAssert(pBestPlot != NULL);
+ doAdvancedStartAction(ADVANCEDSTARTACTION_IMPROVEMENT, pBestPlot->getX_INLINE(), pBestPlot->getY_INLINE(), eBestImprovement, true);
+ iPlotsImproved++;
+ if (pCity->getPopulation() < iPlotsImproved)
+ {
+ doAdvancedStartAction(ADVANCEDSTARTACTION_POP, pBestPlot->getX_INLINE(), pBestPlot->getY_INLINE(), -1, true);
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+
+ while (iPlotsImproved > pCity->getPopulation())
+ {
+ int iPopCost = getAdvancedStartPopCost(true, pCity);
+ if (iPopCost <= 0 || iPopCost > getAdvancedStartPoints())
+ {
+ break;
+ }
+ if (pCity->healthRate() < 0)
+ {
+ break;
+ }
+ doAdvancedStartAction(ADVANCEDSTARTACTION_POP, pPlot->getX_INLINE(), pPlot->getY_INLINE(), -1, true);
+ }
+
+ pCity->AI_updateAssignWork();
+
+ return true;
+}
+
+
+
+
+//Returns false if we have no more points.
+bool CvPlayerAI::AI_advancedStartDoRoute(CvPlot* pFromPlot, CvPlot* pToPlot)
+{
+ FAssert(pFromPlot != NULL);
+ FAssert(pToPlot != NULL);
+
+ FAStarNode* pNode;
+ gDLL->getFAStarIFace()->ForceReset(&GC.getStepFinder());
+ if (gDLL->getFAStarIFace()->GeneratePath(&GC.getStepFinder(), pFromPlot->getX_INLINE(), pFromPlot->getY_INLINE(), pToPlot->getX_INLINE(), pToPlot->getY_INLINE(), false, 0, true))
+ {
+ pNode = gDLL->getFAStarIFace()->GetLastNode(&GC.getStepFinder());
+ if (pNode != NULL)
+ {
+ if (pNode->m_iData1 > (1 + stepDistance(pFromPlot->getX(), pFromPlot->getY(), pToPlot->getX(), pToPlot->getY())))
+ {
+ //Don't build convulted paths.
+ return true;
+ }
+ }
+
+ while (pNode != NULL)
+ {
+ CvPlot* pPlot = GC.getMapINLINE().plotSorenINLINE(pNode->m_iX, pNode->m_iY);
+ RouteTypes eRoute = AI_bestAdvancedStartRoute(pPlot);
+ if (eRoute != NO_ROUTE)
+ {
+ if (getAdvancedStartRouteCost(eRoute, true, pPlot) > getAdvancedStartPoints())
+ {
+ return false;
+ }
+ doAdvancedStartAction(ADVANCEDSTARTACTION_ROUTE, pNode->m_iX, pNode->m_iY, eRoute, true);
+ }
+ pNode = pNode->m_pParent;
+ }
+ }
+ return true;
+}
+void CvPlayerAI::AI_advancedStartRouteTerritory()
+{
+// //This uses a heuristic to create a road network
+// //which is at least effecient if not all inclusive
+// //Basically a human will place roads where they connect
+// //the maximum number of trade groups and this
+// //mimics that.
+//
+//
+// CvPlot* pLoopPlot;
+// CvPlot* pLoopPlot2;
+// int iI, iJ;
+// int iPass;
+//
+//
+// std::vector aiPlotGroups;
+// for (iPass = 4; iPass > 1; --iPass)
+// {
+// for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
+// {
+// pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
+// if ((pLoopPlot != NULL) && (pLoopPlot->getOwner() == getID()) && (pLoopPlot->getRouteType() == NO_ROUTE))
+// {
+// aiPlotGroups.clear();
+// if (pLoopPlot->getPlotGroup(getID()) != NULL)
+// {
+// aiPlotGroups.push_back(pLoopPlot->getPlotGroup(getID())->getID());
+// }
+// for (iJ = 0; iJ < NUM_DIRECTION_TYPES; iJ++)
+// {
+// pLoopPlot2 = plotDirection(pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), (DirectionTypes)iJ);
+// if ((pLoopPlot2 != NULL) && (pLoopPlot2->getRouteType() != NO_ROUTE))
+// {
+// CvPlotGroup* pPlotGroup = pLoopPlot2->getPlotGroup(getID());
+// if (pPlotGroup != NULL)
+// {
+// if (std::find(aiPlotGroups.begin(),aiPlotGroups.end(), pPlotGroup->getID()) == aiPlotGroups.end())
+// {
+// aiPlotGroups.push_back(pPlotGroup->getID());
+// }
+// }
+// }
+// }
+// if ((int)aiPlotGroups.size() >= iPass)
+// {
+// RouteTypes eBestRoute = AI_bestAdvancedStartRoute(pLoopPlot);
+// if (eBestRoute != NO_ROUTE)
+// {
+// doAdvancedStartAction(ADVANCEDSTARTACTION_ROUTE, pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), eBestRoute, true);
+// }
+// }
+// }
+// }
+// }
+//
+// //Maybe try to build road network for mobility but bearing in mind
+// //that routes can't be built outside culture atm. I think workers
+// //can do that just fine.
+
+ CvPlot* pLoopPlot;
+ int iI;
+
+ for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
+ {
+ pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
+ if ((pLoopPlot != NULL) && (pLoopPlot->getOwner() == getID()) && (pLoopPlot->getRouteType() == NO_ROUTE))
+ {
+ if (pLoopPlot->getImprovementType() != NO_IMPROVEMENT)
+ {
+ BonusTypes eBonus = pLoopPlot->getBonusType(getTeam());
+ if (eBonus != NO_BONUS)
+ {
+ if (GC.getImprovementInfo(pLoopPlot->getImprovementType()).isImprovementBonusTrade(eBonus))
+ {
+ int iBonusValue = AI_bonusVal(eBonus, 1);
+ if (iBonusValue > 9)
+ {
+ int iBestValue = 0;
+ CvPlot* pBestPlot = NULL;
+ int iRange = 2;
+ for (int iX = -iRange; iX <= iRange; iX++)
+ {
+ for (int iY = -iRange; iY <= iRange; iY++)
+ {
+ CvPlot* pLoopPlot2 = plotXY(pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), iX, iY);
+ if (pLoopPlot2 != NULL)
+ {
+ if (pLoopPlot2->getOwner() == getID())
+ {
+ if ((pLoopPlot2->isConnectedToCapital()) || pLoopPlot2->isCity())
+ {
+ int iValue = 1000;
+ if (pLoopPlot2->isCity())
+ {
+ iValue += 100;
+ if (pLoopPlot2->getPlotCity()->isCapital())
+ {
+ iValue += 100;
+ }
+ }
+ if (pLoopPlot2->isRoute())
+ {
+ iValue += 100;
+ }
+ int iDistance = GC.getMapINLINE().calculatePathDistance(pLoopPlot, pLoopPlot2);
+ if (iDistance > 0)
+ {
+ iValue /= (1 + iDistance);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ pBestPlot = pLoopPlot2;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (pBestPlot != NULL)
+ {
+ if (!AI_advancedStartDoRoute(pLoopPlot, pBestPlot))
+ {
+ return;
+ }
+ }
+ }
+ }
+ }
+ if (pLoopPlot->getRouteType() == NO_ROUTE)
+ {
+ int iRouteYieldValue = 0;
+ RouteTypes eRoute = (AI_bestAdvancedStartRoute(pLoopPlot, &iRouteYieldValue));
+ if (eRoute != NO_ROUTE && iRouteYieldValue > 0)
+ {
+ doAdvancedStartAction(ADVANCEDSTARTACTION_ROUTE, pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), eRoute, true);
+ }
+ }
+ }
+ }
+ }
+
+ //Connect Cities
+ int iLoop;
+ CvCity* pLoopCity;
+
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ if (!pLoopCity->isCapital() && !pLoopCity->isConnectedToCapital())
+ {
+ int iBestValue = 0;
+ CvPlot* pBestPlot = NULL;
+ int iRange = 5;
+ for (int iX = -iRange; iX <= iRange; iX++)
+ {
+ for (int iY = -iRange; iY <= iRange; iY++)
+ {
+ CvPlot* pLoopPlot = plotXY(pLoopCity->getX_INLINE(), pLoopCity->getY_INLINE(), iX, iY);
+ if ((pLoopPlot != NULL) && (pLoopPlot->getOwner() == getID()))
+ {
+ if ((pLoopPlot->isConnectedToCapital()) || pLoopPlot->isCity())
+ {
+ int iValue = 1000;
+ if (pLoopPlot->isCity())
+ {
+ iValue += 500;
+ if (pLoopPlot->getPlotCity()->isCapital())
+ {
+ iValue += 500;
+ }
+ }
+ if (pLoopPlot->isRoute())
+ {
+ iValue += 100;
+ }
+ int iDistance = GC.getMapINLINE().calculatePathDistance(pLoopCity->plot(), pLoopPlot);
+ if (iDistance > 0)
+ {
+ iValue /= (1 + iDistance);
+
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ pBestPlot = pLoopPlot;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (NULL != pBestPlot)
+ {
+ if (!AI_advancedStartDoRoute(pBestPlot, pLoopCity->plot()))
+ {
+ return;
+ }
+ }
+ }
+ }
+}
+
+
+void CvPlayerAI::AI_doAdvancedStart(bool bNoExit)
+{
+ FAssertMsg(!isBarbarian(), "Should not be called for barbarians!");
+
+ if (NULL == getStartingPlot())
+ {
+ FAssert(false);
+ return;
+ }
+
+ int iLoop;
+ CvCity* pLoopCity;
+
+ int iStartingPoints = getAdvancedStartPoints();
+ int iRevealPoints = (iStartingPoints * 10) / 100;
+ int iMilitaryPoints = (iStartingPoints * (isHuman() ? 17 : (10 + (GC.getLeaderHeadInfo(getPersonalityType()).getBuildUnitProb() / 3)))) / 100;
+ int iCityPoints = iStartingPoints - (iMilitaryPoints + iRevealPoints);
+
+ if (getCapitalCity() != NULL)
+ {
+ AI_advancedStartPlaceCity(getCapitalCity()->plot());
+ }
+ else
+ {
+ for (int iPass = 0; iPass < 2 && NULL == getCapitalCity(); ++iPass)
+ {
+ CvPlot* pBestCapitalPlot = AI_advancedStartFindCapitalPlot();
+
+ if (pBestCapitalPlot != NULL)
+ {
+ if (!AI_advancedStartPlaceCity(pBestCapitalPlot))
+ {
+ FAssertMsg(false, "AS AI: Unexpected failure placing capital");
+ }
+ break;
+ }
+ else
+ {
+ //If this point is reached, the advanced start system is broken.
+ //Find a new starting plot for this player
+ setStartingPlot(findStartingPlot(false), true);
+ //Redo Starting visibility
+ CvPlot* pStartingPlot = getStartingPlot();
+ if (NULL != pStartingPlot)
+ {
+ for (int iPlotLoop = 0; iPlotLoop < GC.getMapINLINE().numPlots(); ++iPlotLoop)
+ {
+ CvPlot* pPlot = GC.getMapINLINE().plotByIndex(iPlotLoop);
+
+ if (plotDistance(pPlot->getX_INLINE(), pPlot->getY_INLINE(), pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE()) <= GC.getDefineINT("ADVANCED_START_SIGHT_RANGE"))
+ {
+ pPlot->setRevealed(getTeam(), true, false, NO_TEAM, false);
+ }
+ }
+ }
+ }
+ }
+
+ if (getCapitalCity() == NULL)
+ {
+ if (!bNoExit)
+ {
+ doAdvancedStartAction(ADVANCEDSTARTACTION_EXIT, -1, -1, -1, true);
+ }
+ return;
+ }
+ }
+
+ iCityPoints -= (iStartingPoints - getAdvancedStartPoints());
+
+ int iLastPointsTotal = getAdvancedStartPoints();
+
+ for (int iPass = 0; iPass < 6; iPass++)
+ {
+ for (int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
+ {
+ CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
+ if (pLoopPlot->isRevealed(getTeam(), false))
+ {
+ if (pLoopPlot->getBonusType(getTeam()) != NO_BONUS)
+ {
+ AI_advancedStartRevealRadius(pLoopPlot, CITY_PLOTS_RADIUS);
+ }
+ else
+ {
+ for (int iJ = 0; iJ < NUM_CARDINALDIRECTION_TYPES; iJ++)
+ {
+ CvPlot* pLoopPlot2 = plotCardinalDirection(pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), (CardinalDirectionTypes)iJ);
+ if ((pLoopPlot2 != NULL) && (getAdvancedStartVisibilityCost(true, pLoopPlot2) > 0))
+ {
+ //Mildly maphackery but any smart human can see the terrain type of a tile.
+ pLoopPlot2->getTerrainType();
+ int iFoodYield = GC.getTerrainInfo(pLoopPlot2->getTerrainType()).getYield(YIELD_FOOD);
+ if (pLoopPlot2->getFeatureType() != NO_FEATURE)
+ {
+ iFoodYield += GC.getFeatureInfo(pLoopPlot2->getFeatureType()).getYieldChange(YIELD_FOOD);
+ }
+ if (((iFoodYield >= 2) && !pLoopPlot2->isFreshWater()) || pLoopPlot2->isHills() || pLoopPlot2->isRiver())
+ {
+ doAdvancedStartAction(ADVANCEDSTARTACTION_VISIBILITY, pLoopPlot2->getX_INLINE(), pLoopPlot2->getY_INLINE(), -1, true);
+ }
+ }
+ }
+ }
+ }
+ if ((iLastPointsTotal - getAdvancedStartPoints()) > iRevealPoints)
+ {
+ break;
+ }
+ }
+ }
+
+ iLastPointsTotal = getAdvancedStartPoints();
+ iCityPoints = std::min(iCityPoints, iLastPointsTotal);
+ int iArea = -1; //getStartingPlot()->getArea();
+
+ //Spend econ points on a tech?
+ int iTechRand = 90 + GC.getGame().getSorenRandNum(20, "AI AS Buy Tech 1");
+ int iTotalTechSpending = 0;
+
+ if (getCurrentEra() == 0)
+ {
+ TechTypes eTech = AI_bestTech(1);
+ if ((eTech != NO_TECH) && !GC.getTechInfo(eTech).isRepeat())
+ {
+ int iTechCost = getAdvancedStartTechCost(eTech, true);
+ if (iTechCost > 0)
+ {
+ doAdvancedStartAction(ADVANCEDSTARTACTION_TECH, -1, -1, eTech, true);
+ iTechRand -= 50;
+ iTotalTechSpending += iTechCost;
+ }
+ }
+ }
+
+ bool bDonePlacingCities = false;
+ for (int iPass = 0; iPass < 100; ++iPass)
+ {
+ int iRand = iTechRand + 10 * getNumCities();
+ if ((iRand > 0) && (GC.getGame().getSorenRandNum(100, "AI AS Buy Tech 2") < iRand))
+ {
+ TechTypes eTech = AI_bestTech(1);
+ if ((eTech != NO_TECH) && !GC.getTechInfo(eTech).isRepeat())
+ {
+ int iTechCost = getAdvancedStartTechCost(eTech, true);
+ if ((iTechCost > 0) && ((iTechCost + iTotalTechSpending) < (iCityPoints / 4)))
+ {
+ doAdvancedStartAction(ADVANCEDSTARTACTION_TECH, -1, -1, eTech, true);
+ iTechRand -= 50;
+ iTotalTechSpending += iTechCost;
+
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ AI_advancedStartPlaceCity(pLoopCity->plot());
+ }
+ }
+ }
+ }
+ int iBestFoundValue = 0;
+ CvPlot* pBestFoundPlot = NULL;
+ AI_updateFoundValues(false);
+ for (int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
+ {
+ CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
+ //if (pLoopPlot->area() == getStartingPlot()->area())
+ {
+ if (plotDistance(getStartingPlot()->getX_INLINE(), getStartingPlot()->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE()) < 9)
+ {
+ if (pLoopPlot->getFoundValue(getID()) > iBestFoundValue)
+ {
+ if (getAdvancedStartCityCost(true, pLoopPlot) > 0)
+ {
+ pBestFoundPlot = pLoopPlot;
+ iBestFoundValue = pLoopPlot->getFoundValue(getID());
+ }
+ }
+ }
+ }
+ }
+
+ if (iBestFoundValue < ((getNumCities() == 0) ? 1 : (500 + 250 * getNumCities())))
+ {
+ bDonePlacingCities = true;
+ }
+ if (!bDonePlacingCities)
+ {
+ int iCost = getAdvancedStartCityCost(true, pBestFoundPlot);
+ if (iCost > getAdvancedStartPoints())
+ {
+ bDonePlacingCities = true;
+ }// at 500pts, we have 200, we spend 100.
+ else if (((iLastPointsTotal - getAdvancedStartPoints()) + iCost) > iCityPoints)
+ {
+ bDonePlacingCities = true;
+ }
+ }
+
+ if (!bDonePlacingCities)
+ {
+ if (!AI_advancedStartPlaceCity(pBestFoundPlot))
+ {
+ FAssertMsg(false, "AS AI: Failed to place city (non-capital)");
+ bDonePlacingCities = true;
+ }
+ }
+
+ if (bDonePlacingCities)
+ {
+ break;
+ }
+ }
+
+
+ bool bDoneWithTechs = false;
+ while (!bDoneWithTechs)
+ {
+ bDoneWithTechs = true;
+ TechTypes eTech = AI_bestTech(1);
+ if (eTech != NO_TECH && !GC.getTechInfo(eTech).isRepeat())
+ {
+ int iTechCost = getAdvancedStartTechCost(eTech, true);
+ if ((iTechCost > 0) && ((iTechCost + iLastPointsTotal - getAdvancedStartPoints()) <= iCityPoints))
+ {
+ doAdvancedStartAction(ADVANCEDSTARTACTION_TECH, -1, -1, eTech, true);
+ bDoneWithTechs = false;
+ }
+ }
+ }
+
+ {
+ //Land
+ AI_advancedStartPlaceExploreUnits(true);
+ if (getCurrentEra() > 2)
+ {
+ //Sea
+ AI_advancedStartPlaceExploreUnits(false);
+ if (GC.getGameINLINE().circumnavigationAvailable())
+ {
+ if (GC.getGameINLINE().getSorenRandNum(GC.getGameINLINE().countCivPlayersAlive(), "AI AS buy 2nd sea explorer") < 2)
+ {
+ AI_advancedStartPlaceExploreUnits(false);
+ }
+ }
+ }
+ }
+
+ AI_advancedStartRouteTerritory();
+
+ bool bDoneBuildings = (iLastPointsTotal - getAdvancedStartPoints()) > iCityPoints;
+ for (int iPass = 0; iPass < 10 && !bDoneBuildings; ++iPass)
+ {
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ BuildingTypes eBuilding = pLoopCity->AI_bestAdvancedStartBuilding(iPass);
+ if (eBuilding != NO_BUILDING)
+ {
+ bDoneBuildings = (iLastPointsTotal - (getAdvancedStartPoints() - getAdvancedStartBuildingCost(eBuilding, true, pLoopCity))) > iCityPoints;
+ if (!bDoneBuildings)
+ {
+ doAdvancedStartAction(ADVANCEDSTARTACTION_BUILDING, pLoopCity->getX_INLINE(), pLoopCity->getY_INLINE(), eBuilding, true);
+ }
+ else
+ {
+ //continue there might be cheaper buildings in other cities we can afford
+ }
+ }
+ }
+ }
+
+ //Units
+ std::vector aeUnitAITypes;
+ aeUnitAITypes.push_back(UNITAI_CITY_DEFENSE);
+ aeUnitAITypes.push_back(UNITAI_WORKER);
+ aeUnitAITypes.push_back(UNITAI_RESERVE);
+ aeUnitAITypes.push_back(UNITAI_COUNTER);
+
+
+ bool bDone = false;
+ for (int iPass = 0; iPass < 10; ++iPass)
+ {
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ if ((iPass == 0) || (pLoopCity->getArea() == getStartingPlot()->getArea()))
+ {
+ CvPlot* pUnitPlot = pLoopCity->plot();
+ //Token defender
+ UnitTypes eBestUnit = AI_bestAdvancedStartUnitAI(pUnitPlot, aeUnitAITypes[iPass % aeUnitAITypes.size()]);
+ if (eBestUnit != NO_UNIT)
+ {
+ if (getAdvancedStartUnitCost(eBestUnit, true, pUnitPlot) > getAdvancedStartPoints())
+ {
+ bDone = true;
+ break;
+ }
+ doAdvancedStartAction(ADVANCEDSTARTACTION_UNIT, pUnitPlot->getX(), pUnitPlot->getY(), eBestUnit, true);
+ }
+ }
+ }
+ }
+
+ if (isHuman())
+ {
+ // remove unhappy population
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ while (pLoopCity->angryPopulation() > 0 && getAdvancedStartPopCost(false, pLoopCity) > 0)
+ {
+ doAdvancedStartAction(ADVANCEDSTARTACTION_POP, pLoopCity->getX_INLINE(), pLoopCity->getY_INLINE(), -1, false);
+ }
+ }
+ }
+
+ if (!bNoExit)
+ {
+ doAdvancedStartAction(ADVANCEDSTARTACTION_EXIT, -1, -1, -1, true);
+ }
+
+}
+
+
+void CvPlayerAI::AI_recalculateFoundValues(int iX, int iY, int iInnerRadius, int iOuterRadius) const
+{
+ CvPlot* pLoopPlot;
+ int iLoopX, iLoopY;
+ int iValue;
+
+ for (iLoopX = -iOuterRadius; iLoopX <= iOuterRadius; iLoopX++)
+ {
+ for (iLoopY = -iOuterRadius; iLoopY <= iOuterRadius; iLoopY++)
+ {
+ pLoopPlot = plotXY(iX, iY, iLoopX, iLoopY);
+ if ((NULL != pLoopPlot) && !AI_isPlotCitySite(pLoopPlot))
+ {
+ if (stepDistance(0, 0, iLoopX, iLoopY) <= iInnerRadius)
+ {
+ if (!((iLoopX == 0) && (iLoopY == 0)))
+ {
+ pLoopPlot->setFoundValue(getID(), 0);
+ }
+ }
+ else
+ {
+ if ((pLoopPlot != NULL) && (pLoopPlot->isRevealed(getTeam(), false)))
+ {
+ long lResult=-1;
+ if(GC.getUSE_GET_CITY_FOUND_VALUE_CALLBACK())
+ {
+ CyArgsList argsList;
+ argsList.add((int)getID());
+ argsList.add(pLoopPlot->getX());
+ argsList.add(pLoopPlot->getY());
+ gDLL->getPythonIFace()->callFunction(PYGameModule, "getCityFoundValue", argsList.makeFunctionArgs(), &lResult);
+ }
+
+ if (lResult == -1)
+ {
+ iValue = AI_foundValue(pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE());
+ }
+ else
+ {
+ iValue = lResult;
+ }
+
+ pLoopPlot->setFoundValue(getID(), iValue);
+
+ if (iValue > pLoopPlot->area()->getBestFoundValue(getID()))
+ {
+ pLoopPlot->area()->setBestFoundValue(getID(), iValue);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+int CvPlayerAI::AI_getMinFoundValue() const
+{
+ int iValue = 600;
+ int iNetCommerce = 1 + getCommerceRate(COMMERCE_GOLD) + getCommerceRate(COMMERCE_RESEARCH) + std::max(0, getGoldPerTurn());
+ int iNetExpenses = calculateInflatedCosts() + std::min(0, getGoldPerTurn());
+
+ iValue *= iNetCommerce;
+ iValue /= std::max(std::max(1, iNetCommerce / 4), iNetCommerce - iNetExpenses);
+
+ if (GET_TEAM(getTeam()).getAnyWarPlanCount(1) > 0)
+ {
+ iValue *= 2;
+ }
+
+ return iValue;
+}
+
+void CvPlayerAI::AI_updateCitySites(int iMinFoundValueThreshold, int iMaxSites) const
+{
+ std::vector::iterator it;
+ int iValue;
+ int iI;
+
+ int iPass = 0;
+ while (iPass < iMaxSites)
+ {
+ //Add a city to the list.
+ int iBestFoundValue = 0;
+ CvPlot* pBestFoundPlot = NULL;
+
+ for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
+ {
+ CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
+ if (pLoopPlot->isRevealed(getTeam(), false))
+ {
+ iValue = pLoopPlot->getFoundValue(getID());
+ if (iValue > iMinFoundValueThreshold)
+ {
+ if (!AI_isPlotCitySite(pLoopPlot))
+ {
+ iValue *= std::min(NUM_CITY_PLOTS * 2, pLoopPlot->area()->getNumUnownedTiles());
+
+ if (iValue > iBestFoundValue)
+ {
+ iBestFoundValue = iValue;
+ pBestFoundPlot = pLoopPlot;
+ }
+ }
+ }
+ }
+ }
+ if (pBestFoundPlot != NULL)
+ {
+ m_aiAICitySites.push_back(GC.getMapINLINE().plotNum(pBestFoundPlot->getX_INLINE(), pBestFoundPlot->getY_INLINE()));
+ AI_recalculateFoundValues(pBestFoundPlot->getX_INLINE(), pBestFoundPlot->getY_INLINE(), CITY_PLOTS_RADIUS, 2 * CITY_PLOTS_RADIUS);
+ }
+ else
+ {
+ break;
+ }
+ iPass++;
+ }
+}
+
+void CvPlayerAI::AI_invalidateCitySites(int iMinFoundValueThreshold) const
+{
+ m_aiAICitySites.clear();
+}
+
+int CvPlayerAI::AI_getNumCitySites() const
+{
+ return m_aiAICitySites.size();
+
+}
+
+bool CvPlayerAI::AI_isPlotCitySite(CvPlot* pPlot) const
+{
+ std::vector::iterator it;
+ int iPlotIndex = GC.getMapINLINE().plotNumINLINE(pPlot->getX_INLINE(), pPlot->getY_INLINE());
+
+ for (it = m_aiAICitySites.begin(); it != m_aiAICitySites.end(); it++)
+ {
+ if ((*it) == iPlotIndex)
+ {
+ return true;
+ }
+ }
+ return false;
+
+}
+
+int CvPlayerAI::AI_getNumAreaCitySites(int iAreaID, int& iBestValue) const
+{
+ std::vector::iterator it;
+ int iCount = 0;
+ iBestValue = 0;
+
+ for (it = m_aiAICitySites.begin(); it != m_aiAICitySites.end(); it++)
+ {
+ CvPlot* pCitySitePlot = GC.getMapINLINE().plotByIndex((*it));
+ if (pCitySitePlot->getArea() == iAreaID)
+ {
+ iCount++;
+ iBestValue = std::max(iBestValue, pCitySitePlot->getFoundValue(getID()));
+ }
+ }
+ return iCount;
+}
+
+int CvPlayerAI::AI_getNumAdjacentAreaCitySites(int iWaterAreaID, int iExcludeArea, int& iBestValue) const
+{
+ std::vector::iterator it;
+ int iCount = 0;
+ iBestValue = 0;
+
+ for (it = m_aiAICitySites.begin(); it != m_aiAICitySites.end(); it++)
+ {
+ CvPlot* pCitySitePlot = GC.getMapINLINE().plotByIndex((*it));
+ if (pCitySitePlot->getArea() != iExcludeArea)
+ {
+ if (pCitySitePlot->isAdjacentToArea(iWaterAreaID))
+ {
+ iCount++;
+ iBestValue = std::max(iBestValue, pCitySitePlot->getFoundValue(getID()));
+ }
+ }
+ }
+ return iCount;
+
+
+}
+
+CvPlot* CvPlayerAI::AI_getCitySite(int iIndex) const
+{
+ FAssert(iIndex < (int)m_aiAICitySites.size());
+ return GC.getMapINLINE().plotByIndex(m_aiAICitySites[iIndex]);
+}
+
+int CvPlayerAI::AI_bestAreaUnitAIValue(UnitAITypes eUnitAI, CvArea* pArea, UnitTypes* peBestUnitType) const
+{
+
+ CvCity* pCity = NULL;
+
+ if (pArea != NULL)
+ {
+ if (getCapitalCity() != NULL)
+ {
+ if (pArea->isWater())
+ {
+ if (getCapitalCity()->plot()->isAdjacentToArea(pArea))
+ {
+ pCity = getCapitalCity();
+ }
+ }
+ else
+ {
+ if (getCapitalCity()->getArea() == pArea->getID())
+ {
+ pCity = getCapitalCity();
+ }
+ }
+ }
+
+ if (NULL == pCity)
+ {
+ CvCity* pLoopCity;
+ int iLoop;
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ if (pArea->isWater())
+ {
+ if (pLoopCity->plot()->isAdjacentToArea(pArea))
+ {
+ pCity = pLoopCity;
+ break;
+ }
+ }
+ else
+ {
+ if (pLoopCity->getArea() == pArea->getID())
+ {
+ pCity = pLoopCity;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return AI_bestCityUnitAIValue(eUnitAI, pCity, peBestUnitType);
+
+}
+
+int CvPlayerAI::AI_bestCityUnitAIValue(UnitAITypes eUnitAI, CvCity* pCity, UnitTypes* peBestUnitType) const
+{
+ UnitTypes eLoopUnit;
+ int iValue;
+ int iBestValue;
+ int iI;
+
+ FAssertMsg(eUnitAI != NO_UNITAI, "UnitAI is not assigned a valid value");
+
+ iBestValue = 0;
+
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ eLoopUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI)));
+
+ if (eLoopUnit != NO_UNIT)
+ {
+ if (!isHuman() || (GC.getUnitInfo(eLoopUnit).getDefaultUnitAIType() == eUnitAI))
+ {
+ if (NULL == pCity ? canTrain(eLoopUnit) : pCity->canTrain(eLoopUnit))
+ {
+ iValue = AI_unitValue(eLoopUnit, eUnitAI, (pCity == NULL) ? NULL : pCity->area());
+ if (iValue > iBestValue)
+ {
+ iBestValue = iValue;
+ if (peBestUnitType != NULL)
+ {
+ *peBestUnitType = eLoopUnit;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return iBestValue;
+}
+
+int CvPlayerAI::AI_calculateTotalBombard(DomainTypes eDomain) const
+{
+ int iI;
+ int iTotalBombard = 0;
+
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ UnitTypes eLoopUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI)));
+ if (eLoopUnit != NO_UNIT)
+ {
+ if (GC.getUnitInfo(eLoopUnit).getDomainType() == eDomain)
+ {
+ int iBombardRate = GC.getUnitInfo(eLoopUnit).getBombardRate();
+
+ if (iBombardRate > 0)
+ {
+ iTotalBombard += iBombardRate * getUnitClassCount((UnitClassTypes)iI);
+ }
+
+ int iBombRate = GC.getUnitInfo(eLoopUnit).getBombRate();
+ if (iBombRate > 0)
+ {
+ iTotalBombard += iBombRate * getUnitClassCount((UnitClassTypes)iI);
+ }
+ }
+ }
+ }
+
+ return iTotalBombard;
+}
+
+void CvPlayerAI::AI_updateBonusValue(BonusTypes eBonus)
+{
+ FAssert(m_aiBonusValue != NULL);
+
+ //reset
+ m_aiBonusValue[eBonus] = -1;
+}
+
+
+void CvPlayerAI::AI_updateBonusValue()
+{
+ PROFILE_FUNC();
+
+ FAssert(m_aiBonusValue != NULL);
+
+ for (int iI = 0; iI < GC.getNumBonusInfos(); iI++)
+ {
+ AI_updateBonusValue((BonusTypes)iI);
+ }
+}
+
+int CvPlayerAI::AI_getUnitClassWeight(UnitClassTypes eUnitClass) const
+{
+ return m_aiUnitClassWeights[eUnitClass] / 100;
+}
+
+int CvPlayerAI::AI_getUnitCombatWeight(UnitCombatTypes eUnitCombat) const
+{
+ return m_aiUnitCombatWeights[eUnitCombat] / 100;
+}
+
+void CvPlayerAI::AI_doEnemyUnitData()
+{
+ std::vector aiUnitCounts(GC.getNumUnitInfos(), 0);
+
+ std::vector aiDomainSums(NUM_DOMAIN_TYPES, 0);
+
+ CLLNode* pUnitNode;
+ CvUnit* pLoopUnit;
+ int iI;
+
+ int iOldTotal = 0;
+ int iNewTotal = 0;
+
+
+ for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
+ {
+
+ CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
+ int iAdjacentAttackers = -1;
+ if (pLoopPlot->isVisible(getTeam(), false))
+ {
+ pUnitNode = pLoopPlot->headUnitNode();
+
+ while (pUnitNode != NULL)
+ {
+ pLoopUnit = ::getUnit(pUnitNode->m_data);
+ pUnitNode = pLoopPlot->nextUnitNode(pUnitNode);
+
+ if (pLoopUnit->canFight())
+ {
+ int iUnitValue = 1;
+ if (atWar(getTeam(), pLoopUnit->getTeam()))
+ {
+ iUnitValue += 10;
+
+ if ((pLoopPlot->getOwnerINLINE() == getID()))
+ {
+ iUnitValue += 15;
+ }
+ else if (atWar(getTeam(), pLoopPlot->getTeam()))
+ {
+ if (iAdjacentAttackers == -1)
+ {
+ iAdjacentAttackers = GET_PLAYER(pLoopPlot->getOwnerINLINE()).AI_adjacentPotentialAttackers(pLoopPlot);
+ }
+ if (iAdjacentAttackers > 0)
+ {
+ iUnitValue += 15;
+ }
+ }
+ }
+ else if (pLoopUnit->getOwnerINLINE() != getID())
+ {
+ iUnitValue += pLoopUnit->canAttack() ? 4 : 1;
+ if (pLoopPlot->getCulture(getID()) > 0)
+ {
+ iUnitValue += pLoopUnit->canAttack() ? 4 : 1;
+ }
+ }
+
+ if (m_aiUnitClassWeights[pLoopUnit->getUnitClassType()] == 0)
+ {
+ iUnitValue *= 4;
+ }
+
+ iUnitValue *= pLoopUnit->baseCombatStr();
+ aiUnitCounts[pLoopUnit->getUnitType()] += iUnitValue;
+ aiDomainSums[pLoopUnit->getDomainType()] += iUnitValue;
+ iNewTotal += iUnitValue;
+ }
+ }
+ }
+ }
+
+ if (iNewTotal == 0)
+ {
+ //This should rarely happen.
+ return;
+ }
+
+ //Decay
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ m_aiUnitClassWeights[iI] -= 100;
+ m_aiUnitClassWeights[iI] *= 3;
+ m_aiUnitClassWeights[iI] /= 4;
+ m_aiUnitClassWeights[iI] = std::max(0, m_aiUnitClassWeights[iI]);
+ }
+
+ for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
+ {
+ if (aiUnitCounts[iI] > 0)
+ {
+ UnitTypes eLoopUnit = (UnitTypes)iI;
+
+ TechTypes eTech = (TechTypes)GC.getUnitInfo((UnitTypes)iI).getPrereqAndTech();
+
+ int iEraDiff = (eTech == NO_TECH) ? 4 : std::min(4, getCurrentEra() - GC.getTechInfo(eTech).getEra());
+
+ if (iEraDiff > 1)
+ {
+ iEraDiff -= 1;
+ aiUnitCounts[iI] *= 3 - iEraDiff;
+ aiUnitCounts[iI] /= 3;
+ }
+ FAssert(aiDomainSums[GC.getUnitInfo(eLoopUnit).getDomainType()] > 0);
+ m_aiUnitClassWeights[GC.getUnitInfo(eLoopUnit).getUnitClassType()] += (5000 * aiUnitCounts[iI]) / std::max(1, aiDomainSums[GC.getUnitInfo(eLoopUnit).getDomainType()]);
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); ++iI)
+ {
+ m_aiUnitCombatWeights[iI] = 0;
+ }
+
+ for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ if (m_aiUnitClassWeights[iI] > 0)
+ {
+ UnitTypes eUnit = (UnitTypes)GC.getUnitClassInfo((UnitClassTypes)iI).getDefaultUnitIndex();
+ m_aiUnitCombatWeights[GC.getUnitInfo(eUnit).getUnitCombatType()] += m_aiUnitClassWeights[iI];
+
+ }
+ }
+
+ for (iI = 0; iI < GC.getNumUnitCombatInfos(); iI++)
+ {
+ if (m_aiUnitCombatWeights[iI] > 25)
+ {
+ m_aiUnitCombatWeights[iI] += 2500;
+ }
+ else if (m_aiUnitCombatWeights[iI] > 0)
+ {
+ m_aiUnitCombatWeights[iI] += 1000;
+ }
+ }
+}
+
+int CvPlayerAI::AI_calculateUnitAIViability(UnitAITypes eUnitAI, DomainTypes eDomain) const
+{
+ int iBestUnitAIStrength = 0;
+ int iBestOtherStrength = 0;
+
+ for (int iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
+ {
+ UnitTypes eLoopUnit = (UnitTypes)GC.getUnitClassInfo((UnitClassTypes)iI).getDefaultUnitIndex();
+ CvUnitInfo& kUnitInfo = GC.getUnitInfo((UnitTypes)iI);
+ if (kUnitInfo.getDomainType() == eDomain)
+ {
+
+ TechTypes eTech = (TechTypes)kUnitInfo.getPrereqAndTech();
+ if ((m_aiUnitClassWeights[iI] > 0) || GET_TEAM(getTeam()).isHasTech((eTech)))
+ {
+ if (kUnitInfo.getUnitAIType(eUnitAI))
+ {
+ iBestUnitAIStrength = std::max(iBestUnitAIStrength, kUnitInfo.getCombat());
+ }
+
+ iBestOtherStrength = std::max(iBestOtherStrength, kUnitInfo.getCombat());
+ }
+ }
+ }
+
+ return (100 * iBestUnitAIStrength) / std::max(1, iBestOtherStrength);
+}
+
+ReligionTypes CvPlayerAI::AI_chooseReligion()
+{
+ ReligionTypes eFavorite = (ReligionTypes)GC.getLeaderHeadInfo(getLeaderType()).getFavoriteReligion();
+ if (NO_RELIGION != eFavorite && !GC.getGameINLINE().isReligionFounded(eFavorite))
+ {
+ return eFavorite;
+ }
+
+ std::vector aeReligions;
+ for (int iReligion = 0; iReligion < GC.getNumReligionInfos(); ++iReligion)
+ {
+ if (!GC.getGameINLINE().isReligionFounded((ReligionTypes)iReligion))
+ {
+ aeReligions.push_back((ReligionTypes)iReligion);
+ }
+ }
+
+ if (aeReligions.size() > 0)
+ {
+ return aeReligions[GC.getGameINLINE().getSorenRandNum(aeReligions.size(), "AI pick religion")];
+ }
+
+ return NO_RELIGION;
+}
+
+int CvPlayerAI::AI_getAttitudeWeight(PlayerTypes ePlayer) const
+{
+ int iAttitudeWeight = 0;
+ switch (AI_getAttitude(ePlayer))
+ {
+ case ATTITUDE_FURIOUS:
+ iAttitudeWeight = -100;
+ break;
+ case ATTITUDE_ANNOYED:
+ iAttitudeWeight = -50;
+ break;
+ case ATTITUDE_CAUTIOUS:
+ iAttitudeWeight = 0;
+ break;
+ case ATTITUDE_PLEASED:
+ iAttitudeWeight = 50;
+ break;
+ case ATTITUDE_FRIENDLY:
+ iAttitudeWeight = 100;
+ break;
+ }
+
+ return iAttitudeWeight;
+}
+
+int CvPlayerAI::AI_getPlotAirbaseValue(CvPlot* pPlot) const
+{
+ PROFILE_FUNC();
+
+ FAssert(pPlot != NULL);
+
+ if (pPlot->getTeam() != getTeam())
+ {
+ return 0;
+ }
+
+ if (pPlot->isCityRadius())
+ {
+ CvCity* pWorkingCity = pPlot->getWorkingCity();
+ if (pWorkingCity != NULL)
+ {
+ if (pWorkingCity->AI_getBestBuild(pWorkingCity->getCityPlotIndex(pPlot)) != NO_BUILD)
+ {
+ return 0;
+ }
+ if (pPlot->getImprovementType() != NO_IMPROVEMENT)
+ {
+ CvImprovementInfo &kImprovementInfo = GC.getImprovementInfo(pPlot->getImprovementType());
+ if (!kImprovementInfo.isActsAsCity())
+ {
+ return 0;
+ }
+ }
+ }
+ }
+
+ int iMinOtherCityDistance = MAX_INT;
+ CvPlot* iMinOtherCityPlot = NULL;
+
+ int iMinFriendlyCityDistance = MAX_INT;
+ CvPlot* iMinFriendlyCityPlot = NULL;
+
+ int iOtherCityCount = 0;
+
+ int iRange = 4;
+ for (int iX = -iRange; iX <= iRange; iX++)
+ {
+ for (int iY = -iRange; iY <= iRange; iY++)
+ {
+ CvPlot* pLoopPlot = plotXY(pPlot->getX_INLINE(), pPlot->getY_INLINE(), iX, iY);
+ if ((pLoopPlot != NULL) && (pPlot != pLoopPlot))
+ {
+ int iDistance = plotDistance(pPlot->getX_INLINE(), pPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE());
+
+ if (pLoopPlot->getTeam() == getTeam())
+ {
+ if (pLoopPlot->isCity(true))
+ {
+ if (1 == iDistance)
+ {
+ return 0;
+ }
+ if (iDistance < iMinFriendlyCityDistance)
+ {
+ iMinFriendlyCityDistance = iDistance;
+ iMinFriendlyCityPlot = pLoopPlot;
+ }
+ }
+ }
+ else
+ {
+ if (pLoopPlot->isOwned())
+ {
+ if (pLoopPlot->isCity(false))
+ {
+ if (iDistance < iMinOtherCityDistance)
+ {
+ iMinOtherCityDistance = iDistance;
+ iMinOtherCityPlot = pLoopPlot;
+ iOtherCityCount++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (0 == iOtherCityCount)
+ {
+ return 0;
+ }
+
+// if (iMinFriendlyCityPlot != NULL)
+// {
+// FAssert(iMinOtherCityPlot != NULL);
+// if (plotDistance(iMinFriendlyCityPlot->getX_INLINE(), iMinFriendlyCityPlot->getY_INLINE(), iMinOtherCityPlot->getX_INLINE(), iMinOtherCityPlot->getY_INLINE()) < (iMinOtherCityDistance - 1))
+// {
+// return 0;
+// }
+// }
+
+// if (iMinOtherCityPlot != NULL)
+// {
+// CvCity* pNearestCity = GC.getMapINLINE().findCity(iMinOtherCityPlot->getX_INLINE(), iMinOtherCityPlot->getY_INLINE(), NO_PLAYER, getTeam(), false);
+// if (NULL == pNearestCity)
+// {
+// return 0;
+// }
+// if (plotDistance(pNearestCity->getX_INLINE(), pNearestCity->getY_INLINE(), iMinOtherCityPlot->getX_INLINE(), iMinOtherCityPlot->getY_INLINE()) < iRange)
+// {
+// return 0;
+// }
+// }
+
+
+ int iDefenseModifier = pPlot->defenseModifier(getTeam(), false);
+// if (iDefenseModifier <= 0)
+// {
+// return 0;
+// }
+
+ int iValue = iOtherCityCount * 50;
+ iValue *= 100 + (2 * (iDefenseModifier + (pPlot->isHills() ? 25 : 0)));
+ iValue /= 100;
+
+ return iValue;
+}
+
+int CvPlayerAI::AI_getPlotCanalValue(CvPlot* pPlot) const
+{
+ PROFILE_FUNC();
+
+ FAssert(pPlot != NULL);
+
+ if (pPlot->isOwned())
+ {
+ if (pPlot->getTeam() != getTeam())
+ {
+ return 0;
+ }
+ if (pPlot->isCityRadius())
+ {
+ CvCity* pWorkingCity = pPlot->getWorkingCity();
+ if (pWorkingCity != NULL)
+ {
+ if (pWorkingCity->AI_getBestBuild(pWorkingCity->getCityPlotIndex(pPlot)) != NO_BUILD)
+ {
+ return 0;
+ }
+ if (pPlot->getImprovementType() != NO_IMPROVEMENT)
+ {
+ CvImprovementInfo &kImprovementInfo = GC.getImprovementInfo(pPlot->getImprovementType());
+ if (!kImprovementInfo.isActsAsCity())
+ {
+ return 0;
+ }
+ }
+ }
+ }
+ }
+
+ for (int iI = 0; iI < NUM_DIRECTION_TYPES; iI++)
+ {
+ CvPlot* pLoopPlot = plotDirection(pPlot->getX_INLINE(), pPlot->getY_INLINE(), (DirectionTypes)iI);
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->isCity(true))
+ {
+ return 0;
+ }
+ }
+ }
+
+ CvArea* pSecondWaterArea = pPlot->secondWaterArea();
+ if (pSecondWaterArea == NULL)
+ {
+ return 0;
+ }
+
+ return 10 * std::min(0, pSecondWaterArea->getNumTiles() - 2);
+}
+
+//This returns a positive number equal approximately to the sum
+//of the percentage values of each unit (there is no need to scale the output by iHappy)
+//100 * iHappy means a high value.
+int CvPlayerAI::AI_getHappinessWeight(int iHappy, int iExtraPop) const
+{
+ int iWorstHappy = 0;
+ int iBestHappy = 0;
+ int iTotalUnhappy = 0;
+ int iTotalHappy = 0;
+ int iLoop;
+ CvCity* pLoopCity;
+ int iCount = 0;
+
+ if (0 == iHappy)
+ {
+ iHappy = 1;
+ }
+ int iValue = 0;
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ int iCityHappy = pLoopCity->happyLevel() - pLoopCity->unhappyLevel(iExtraPop);
+
+ iCityHappy -= std::max(0, pLoopCity->getCommerceHappiness());
+ int iHappyNow = iCityHappy;
+ int iHappyThen = iCityHappy + iHappy;
+
+ //Integration
+ int iTempValue = (((100 * iHappyThen - 10 * iHappyThen * iHappyThen)) - (100 * iHappyNow - 10 * iHappyNow * iHappyNow));
+ if (iHappy > 0)
+ {
+ iValue += std::max(0, iTempValue);
+ }
+ else
+ {
+ iValue += std::max(0, -iTempValue);
+ }
+
+ iCount++;
+ if (iCount > 6)
+ {
+ break;
+ }
+ }
+
+ return (0 == iCount) ? 50 * iHappy : iValue / iCount;
+}
+
+int CvPlayerAI::AI_getHealthWeight(int iHealth, int iExtraPop) const
+{
+ int iWorstHealth = 0;
+ int iBestHealth = 0;
+ int iTotalUnhappy = 0;
+ int iTotalHealth = 0;
+ int iLoop;
+ CvCity* pLoopCity;
+ int iCount = 0;
+
+ if (0 == iHealth)
+ {
+ iHealth = 1;
+ }
+ int iValue = 0;
+ for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
+ {
+ int iCityHealth = pLoopCity->goodHealth() - pLoopCity->badHealth(false, iExtraPop);
+
+ int iHealthNow = iCityHealth;
+ int iHealthThen = iCityHealth + iHealth;
+
+ //Integration
+ int iTempValue = (((100 * iHealthThen - 6 * iHealthThen * iHealthThen)) - (100 * iHealthNow - 6 * iHealthNow * iHealthNow));
+ if (iHealth > 0)
+ {
+ iValue += std::max(0, iTempValue);
+ }
+ else
+ {
+ iValue += std::max(0, -iTempValue);
+ }
+ iCount++;
+ if (iCount > 6)
+ {
+ break;
+ }
+ }
+
+ return (0 == iCount) ? 50 : iValue / iCount;
+}
+
+void CvPlayerAI::AI_invalidateCloseBordersAttitudeCache()
+{
+ for (int i = 0; i < MAX_PLAYERS; ++i)
+ {
+ m_aiCloseBordersAttitudeCache[i] = MAX_INT;
+ }
+}
+
+bool CvPlayerAI::AI_isPlotThreatened(CvPlot* pPlot, int iRange, bool bTestMoves) const
+{
+ PROFILE_FUNC();
+
+ CvArea *pPlotArea = pPlot->area();
+
+ if (iRange == -1)
+ {
+ iRange = DANGER_RANGE;
+ }
+
+ for (int iDX = -iRange; iDX <= iRange; iDX++)
+ {
+ for (int iDY = -iRange; iDY <= iRange; iDY++)
+ {
+ CvPlot* pLoopPlot = plotXY(pPlot->getX_INLINE(), pPlot->getY_INLINE(), iDX, iDY);
+
+ if (pLoopPlot != NULL)
+ {
+ if (pLoopPlot->area() == pPlotArea)
+ {
+ for (CLLNode* pUnitNode = pLoopPlot->headUnitNode(); pUnitNode != NULL; pUnitNode = pLoopPlot->nextUnitNode(pUnitNode))
+ {
+ CvUnit* pLoopUnit = ::getUnit(pUnitNode->m_data);
+ if (pLoopUnit->isEnemy(getTeam()) && pLoopUnit->canAttack() && !pLoopUnit->isInvisible(getTeam(), false))
+ {
+ if (pLoopUnit->canMoveOrAttackInto(pPlot))
+ {
+ int iPathTurns = 0;
+ if (bTestMoves)
+ {
+ if (!pLoopUnit->getGroup()->generatePath(pLoopPlot, pPlot, MOVE_MAX_MOVES | MOVE_IGNORE_DANGER, false, &iPathTurns))
+ {
+ iPathTurns = MAX_INT;
+ }
+ }
+
+ if (iPathTurns <= 1)
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+bool CvPlayerAI::AI_isFirstTech(TechTypes eTech) const
+{
+ for (int iI = 0; iI < GC.getNumReligionInfos(); iI++)
+ {
+ if (GC.getReligionInfo((ReligionTypes)iI).getTechPrereq() == eTech)
+ {
+ if (!(GC.getGameINLINE().isReligionSlotTaken((ReligionTypes)iI)))
+ {
+ return true;
+ }
+ }
+ }
+
+ if (GC.getGameINLINE().countKnownTechNumTeams(eTech) == 0)
+ {
+ if ((getTechFreeUnit(eTech) != NO_UNIT) ||
+ (GC.getTechInfo(eTech).getFirstFreeTechs() > 0))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
diff --git a/CvGameCoreDLL/CvPlot.cpp b/CvGameCoreDLL/CvPlot.cpp
index 3685ea8..cd87806 100644
--- a/CvGameCoreDLL/CvPlot.cpp
+++ b/CvGameCoreDLL/CvPlot.cpp
@@ -5874,6 +5874,7 @@ int CvPlot::calculateYield(YieldTypes eYield, bool bDisplay) const
RouteTypes eRoute;
PlayerTypes ePlayer;
bool bCity;
+ bool bCapital;
int iYield;
if (bDisplay && GC.getGameINLINE().isDebugMode())
@@ -5892,6 +5893,7 @@ int CvPlot::calculateYield(YieldTypes eYield, bool bDisplay) const
}
bCity = false;
+ bCapital = false;
if (bDisplay)
{
@@ -5932,6 +5934,11 @@ int CvPlot::calculateYield(YieldTypes eYield, bool bDisplay) const
if (!bDisplay || pCity->isRevealed(GC.getGameINLINE().getActiveTeam(), false))
{
iYield += GC.getYieldInfo(eYield).getCityChange();
+ if(pCity->isCapital()) {
+ // AGDM addition
+ iYield += GC.getYieldInfo(eYield).getCapitalChange();
+ bCapital = true;
+ }
if (GC.getYieldInfo(eYield).getPopulationChangeDivisor() != 0)
{
iYield += ((pCity->getPopulation() + GC.getYieldInfo(eYield).getPopulationChangeOffset()) / GC.getYieldInfo(eYield).getPopulationChangeDivisor());
@@ -5978,6 +5985,11 @@ int CvPlot::calculateYield(YieldTypes eYield, bool bDisplay) const
if (bCity)
{
iYield = std::max(iYield, GC.getYieldInfo(eYield).getMinCity());
+ if (bCapital)
+ {
+ // AGDM addition
+ iYield = std::max(iYield, GC.getYieldInfo(eYield).getMinCapital());
+ }
}
iYield += GC.getGameINLINE().getPlotExtraYield(m_iX, m_iY, eYield);
diff --git a/CvGameCoreDLL/CvTeam.cpp b/CvGameCoreDLL/CvTeam.cpp
index 7de7ca2..ccf6d88 100644
--- a/CvGameCoreDLL/CvTeam.cpp
+++ b/CvGameCoreDLL/CvTeam.cpp
@@ -2388,8 +2388,20 @@ int CvTeam::getResearchCost(TechTypes eTech) const
iCost *= GC.getHandicapInfo(getHandicapType()).getResearchPercent();
iCost /= 100;
- iCost *= GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getResearchPercent();
- iCost /= 100;
+ int iWorldSizeModifier = GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getResearchPercent();
+ if(GC.getDefineINT("TECH_COST_SCALING_ALGORITHM") == 1)
+ {
+ // AGDM addition, use algorithm described here: http://realmsbeyond.net/forums/showthread.php?tid=6632&pid=465879#pid465879
+ // ((log(cost of tech) / log (40) - 1) * (1.2X + 0.3)
+ double fX = (log((double)GC.getTechInfo(eTech).getResearchCost()) / log((double)40.0)) - 1;
+ fX *= (((double)iWorldSizeModifier-100.0)*0.012 + 0.3);
+ iCost = (int)(iCost * (1.0 + fX));
+ }
+ else
+ {
+ iCost *= iWorldSizeModifier;
+ iCost /= 100;
+ }
iCost *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getResearchPercent();
iCost /= 100;
diff --git a/CvGameCoreDLL/CyEnumsInterface.cpp b/CvGameCoreDLL/CyEnumsInterface.cpp
new file mode 100644
index 0000000..6377bf7
--- /dev/null
+++ b/CvGameCoreDLL/CyEnumsInterface.cpp
@@ -0,0 +1,1920 @@
+#include "CvGameCoreDLL.h"
+#include"CvEnums.h"
+
+#include "CvGameCoreDLLUnDefNew.h"
+# include
+#include "CvGameCoreDLLDefNew.h"
+
+//
+// Python interface for free enums
+//
+
+void CyEnumsPythonInterface()
+{
+ OutputDebugString("Python Extension Module - CyEnumsPythonInterface\n");
+
+ python::enum_("GameStateTypes")
+ .value("GAMESTATE_ON", GAMESTATE_ON)
+ .value("GAMESTATE_OVER", GAMESTATE_OVER)
+ .value("GAMESTATE_EXTENDED", GAMESTATE_EXTENDED)
+ ;
+
+ python::enum_("PopupStates")
+ .value("POPUPSTATE_IMMEDIATE", POPUPSTATE_IMMEDIATE)
+ .value("POPUPSTATE_QUEUED", POPUPSTATE_QUEUED)
+ .value("POPUPSTATE_MINIMIZED", POPUPSTATE_MINIMIZED)
+ ;
+
+ python::enum_("CameraLookAtTypes")
+ .value("CAMERALOOKAT_NORMAL", CAMERALOOKAT_NORMAL)
+ .value("CAMERALOOKAT_CITY_ZOOM_IN", CAMERALOOKAT_CITY_ZOOM_IN)
+ .value("CAMERALOOKAT_BATTLE", CAMERALOOKAT_BATTLE)
+ .value("CAMERALOOKAT_BATTLE_ZOOM_IN", CAMERALOOKAT_BATTLE_ZOOM_IN)
+ .value("CAMERALOOKAT_IMMEDIATE", CAMERALOOKAT_IMMEDIATE)
+ ;
+
+ python::enum_("CameraMovementSpeeds")
+ .value("CAMERAMOVEMENTSPEED_NORMAL", CAMERAMOVEMENTSPEED_NORMAL)
+ .value("CAMERAMOVEMENTSPEED_SLOW", CAMERAMOVEMENTSPEED_SLOW)
+ .value("CAMERAMOVEMENTSPEED_FAST", CAMERAMOVEMENTSPEED_FAST)
+ ;
+
+ python::enum_("ZoomLevelTypes")
+ .value("ZOOM_UNKNOWN", ZOOM_UNKNOWN)
+ .value("ZOOM_GLOBEVIEW", ZOOM_GLOBEVIEW)
+ .value("ZOOM_NORMAL", ZOOM_NORMAL)
+ .value("ZOOM_DETAIL", ZOOM_DETAIL)
+ ;
+
+ python::enum_("DirectionTypes")
+ .value("NO_DIRECTION", NO_DIRECTION)
+ .value("DIRECTION_NORTH", DIRECTION_NORTH)
+ .value("DIRECTION_NORTHEAST", DIRECTION_NORTHEAST)
+ .value("DIRECTION_EAST", DIRECTION_EAST)
+ .value("DIRECTION_SOUTHEAST", DIRECTION_SOUTHEAST)
+ .value("DIRECTION_SOUTH", DIRECTION_SOUTH)
+ .value("DIRECTION_SOUTHWEST", DIRECTION_SOUTHWEST)
+ .value("DIRECTION_WEST", DIRECTION_WEST)
+ .value("DIRECTION_NORTHWEST", DIRECTION_NORTHWEST)
+ .value("NUM_DIRECTION_TYPES", NUM_DIRECTION_TYPES)
+ ;
+
+ python::enum_("CardinalDirectionTypes")
+ .value("NO_CARDINALDIRECTION", NO_CARDINALDIRECTION)
+ .value("CARDINALDIRECTION_NORTH", CARDINALDIRECTION_NORTH)
+ .value("CARDINALDIRECTION_EAST", CARDINALDIRECTION_EAST)
+ .value("CARDINALDIRECTION_SOUTH", CARDINALDIRECTION_SOUTH)
+ .value("CARDINALDIRECTION_WEST", CARDINALDIRECTION_WEST)
+ .value("NUM_CARDINALDIRECTION_TYPES", NUM_CARDINALDIRECTION_TYPES)
+ ;
+
+ python::enum_("ColorTypes")
+ .value("NO_COLOR", NO_COLOR)
+ ;
+
+ python::enum_("PlayerColorTypes")
+ .value("NO_PLAYERCOLOR", NO_PLAYERCOLOR)
+ ;
+
+ python::enum_("PlotStyles")
+ .value("PLOT_STYLE_NONE", PLOT_STYLE_NONE)
+ .value("PLOT_STYLE_NUMPAD_1", PLOT_STYLE_NUMPAD_1)
+ .value("PLOT_STYLE_NUMPAD_2", PLOT_STYLE_NUMPAD_2)
+ .value("PLOT_STYLE_NUMPAD_3", PLOT_STYLE_NUMPAD_3)
+ .value("PLOT_STYLE_NUMPAD_4", PLOT_STYLE_NUMPAD_4)
+ .value("PLOT_STYLE_NUMPAD_6", PLOT_STYLE_NUMPAD_6)
+ .value("PLOT_STYLE_NUMPAD_7", PLOT_STYLE_NUMPAD_7)
+ .value("PLOT_STYLE_NUMPAD_8", PLOT_STYLE_NUMPAD_8)
+ .value("PLOT_STYLE_NUMPAD_9", PLOT_STYLE_NUMPAD_9)
+ .value("PLOT_STYLE_NUMPAD_1_ANGLED", PLOT_STYLE_NUMPAD_1_ANGLED)
+ .value("PLOT_STYLE_NUMPAD_2_ANGLED", PLOT_STYLE_NUMPAD_2_ANGLED)
+ .value("PLOT_STYLE_NUMPAD_3_ANGLED", PLOT_STYLE_NUMPAD_3_ANGLED)
+ .value("PLOT_STYLE_NUMPAD_4_ANGLED", PLOT_STYLE_NUMPAD_4_ANGLED)
+ .value("PLOT_STYLE_NUMPAD_6_ANGLED", PLOT_STYLE_NUMPAD_6_ANGLED)
+ .value("PLOT_STYLE_NUMPAD_7_ANGLED", PLOT_STYLE_NUMPAD_7_ANGLED)
+ .value("PLOT_STYLE_NUMPAD_8_ANGLED", PLOT_STYLE_NUMPAD_8_ANGLED)
+ .value("PLOT_STYLE_NUMPAD_9_ANGLED", PLOT_STYLE_NUMPAD_9_ANGLED)
+ .value("PLOT_STYLE_BOX_FILL", PLOT_STYLE_BOX_FILL)
+ .value("PLOT_STYLE_BOX_OUTLINE", PLOT_STYLE_BOX_OUTLINE)
+ .value("PLOT_STYLE_RIVER_SOUTH", PLOT_STYLE_RIVER_SOUTH)
+ .value("PLOT_STYLE_RIVER_EAST", PLOT_STYLE_RIVER_EAST)
+ .value("PLOT_STYLE_SIDE_ARROWS", PLOT_STYLE_SIDE_ARROWS)
+ .value("PLOT_STYLE_CIRCLE", PLOT_STYLE_CIRCLE)
+ .value("PLOT_STYLE_TARGET", PLOT_STYLE_TARGET)
+ .value("PLOT_STYLE_DOT_TARGET", PLOT_STYLE_DOT_TARGET)
+ .value("PLOT_STYLE_WAVES", PLOT_STYLE_WAVES)
+ .value("PLOT_STYLE_DOTS", PLOT_STYLE_DOTS)
+ .value("PLOT_STYLE_CIRCLES", PLOT_STYLE_CIRCLES)
+ ;
+
+ python::enum_("PlotLandscapeLayers")
+ .value("PLOT_LANDSCAPE_LAYER_ALL", PLOT_LANDSCAPE_LAYER_ALL)
+ .value("PLOT_LANDSCAPE_LAYER_BASE", PLOT_LANDSCAPE_LAYER_BASE)
+ .value("PLOT_LANDSCAPE_LAYER_RECOMMENDED_PLOTS", PLOT_LANDSCAPE_LAYER_RECOMMENDED_PLOTS)
+ .value("PLOT_LANDSCAPE_LAYER_WORLD_BUILDER", PLOT_LANDSCAPE_LAYER_WORLD_BUILDER)
+ .value("PLOT_LANDSCAPE_LAYER_NUMPAD_HELP", PLOT_LANDSCAPE_LAYER_NUMPAD_HELP)
+ .value("PLOT_LANDSCAPE_LAYER_REVEALED_PLOTS", PLOT_LANDSCAPE_LAYER_REVEALED_PLOTS)
+ ;
+
+ python::enum_("AreaBorderLayers")
+ .value("AREA_BORDER_LAYER_REVEALED_PLOTS", AREA_BORDER_LAYER_REVEALED_PLOTS)
+ .value("AREA_BORDER_LAYER_WORLD_BUILDER", AREA_BORDER_LAYER_WORLD_BUILDER)
+ .value("AREA_BORDER_LAYER_FOUNDING_BORDER", AREA_BORDER_LAYER_FOUNDING_BORDER)
+ .value("AREA_BORDER_LAYER_CITY_RADIUS", AREA_BORDER_LAYER_CITY_RADIUS)
+ .value("AREA_BORDER_LAYER_RANGED", AREA_BORDER_LAYER_RANGED)
+ .value("AREA_BORDER_LAYER_HIGHLIGHT_PLOT", AREA_BORDER_LAYER_HIGHLIGHT_PLOT)
+ .value("AREA_BORDER_LAYER_BLOCKADING", AREA_BORDER_LAYER_BLOCKADING)
+ .value("AREA_BORDER_LAYER_BLOCKADED", AREA_BORDER_LAYER_BLOCKADED)
+ .value("NUM_AREA_BORDER_LAYERS", NUM_AREA_BORDER_LAYERS)
+ ;
+
+ python::enum_("InterfaceModeTypes")
+ .value("NO_INTERFACEMODE", NO_INTERFACEMODE)
+ .value("INTERFACEMODE_SELECTION", INTERFACEMODE_SELECTION)
+ .value("INTERFACEMODE_PING", INTERFACEMODE_PING)
+ .value("INTERFACEMODE_SIGN", INTERFACEMODE_SIGN)
+ .value("INTERFACEMODE_GRIP", INTERFACEMODE_GRIP)
+ .value("INTERFACEMODE_GLOBELAYER_INPUT", INTERFACEMODE_GLOBELAYER_INPUT)
+ .value("INTERFACEMODE_GO_TO", INTERFACEMODE_GO_TO)
+ .value("INTERFACEMODE_GO_TO_TYPE", INTERFACEMODE_GO_TO_TYPE)
+ .value("INTERFACEMODE_GO_TO_ALL", INTERFACEMODE_GO_TO_ALL)
+ .value("INTERFACEMODE_ROUTE_TO", INTERFACEMODE_ROUTE_TO)
+ .value("INTERFACEMODE_AIRLIFT", INTERFACEMODE_AIRLIFT)
+ .value("INTERFACEMODE_NUKE", INTERFACEMODE_NUKE)
+ .value("INTERFACEMODE_RECON", INTERFACEMODE_RECON)
+ .value("INTERFACEMODE_PARADROP", INTERFACEMODE_PARADROP)
+ .value("INTERFACEMODE_AIRBOMB", INTERFACEMODE_AIRBOMB)
+ .value("INTERFACEMODE_RANGE_ATTACK", INTERFACEMODE_RANGE_ATTACK)
+ .value("INTERFACEMODE_AIRSTRIKE", INTERFACEMODE_AIRSTRIKE)
+ .value("INTERFACEMODE_REBASE", INTERFACEMODE_REBASE)
+ .value("INTERFACEMODE_PYTHON_PICK_PLOT", INTERFACEMODE_PYTHON_PICK_PLOT)
+ .value("INTERFACEMODE_SAVE_PLOT_NIFS", INTERFACEMODE_SAVE_PLOT_NIFS)
+ .value("NUM_INTERFACEMODE_TYPES", NUM_INTERFACEMODE_TYPES)
+ ;
+
+ python::enum_("InterfaceMessageTypes")
+ .value("NO_MESSAGE_TYPE", NO_MESSAGE_TYPE)
+ .value("MESSAGE_TYPE_INFO", MESSAGE_TYPE_INFO)
+ .value("MESSAGE_TYPE_DISPLAY_ONLY", MESSAGE_TYPE_DISPLAY_ONLY)
+ .value("MESSAGE_TYPE_MAJOR_EVENT", MESSAGE_TYPE_MAJOR_EVENT)
+ .value("MESSAGE_TYPE_MINOR_EVENT", MESSAGE_TYPE_MINOR_EVENT)
+ .value("MESSAGE_TYPE_CHAT", MESSAGE_TYPE_CHAT)
+ .value("MESSAGE_TYPE_COMBAT_MESSAGE", MESSAGE_TYPE_COMBAT_MESSAGE)
+ .value("MESSAGE_TYPE_QUEST", MESSAGE_TYPE_QUEST)
+ .value("NUM_INTERFACE_MESSAGE_TYPES", NUM_INTERFACE_MESSAGE_TYPES)
+ ;
+
+ python::enum_("MinimapModeTypes")
+ .value("NO_MINIMAPMODE", NO_MINIMAPMODE)
+ .value("MINIMAPMODE_TERRITORY", MINIMAPMODE_TERRITORY)
+ .value("MINIMAPMODE_TERRAIN", MINIMAPMODE_TERRAIN)
+ .value("MINIMAPMODE_REPLAY", MINIMAPMODE_REPLAY)
+ .value("MINIMAPMODE_MILITARY", MINIMAPMODE_MILITARY)
+ .value("NUM_MINIMAPMODE_TYPES", NUM_MINIMAPMODE_TYPES)
+ ;
+
+ python::enum_("EngineDirtyBits")
+ .value("GlobeTexture_DIRTY_BIT", GlobeTexture_DIRTY_BIT)
+ .value("MinimapTexture_DIRTY_BIT", MinimapTexture_DIRTY_BIT)
+ .value("CultureBorders_DIRTY_BIT", CultureBorders_DIRTY_BIT)
+ .value("NUM_ENGINE_DIRTY_BITS", NUM_ENGINE_DIRTY_BITS)
+ ;
+
+ python::enum_("InterfaceDirtyBits")
+ .value("SelectionCamera_DIRTY_BIT", SelectionCamera_DIRTY_BIT)
+ .value("Fog_DIRTY_BIT", Fog_DIRTY_BIT)
+ .value("GlobeLayer_DIRTY_BIT", GlobeLayer_DIRTY_BIT)
+ .value("GlobeInfo_DIRTY_BIT", GlobeInfo_DIRTY_BIT)
+ .value("Waypoints_DIRTY_BIT", Waypoints_DIRTY_BIT)
+ .value("PercentButtons_DIRTY_BIT", PercentButtons_DIRTY_BIT)
+ .value("MiscButtons_DIRTY_BIT", MiscButtons_DIRTY_BIT)
+ .value("PlotListButtons_DIRTY_BIT", PlotListButtons_DIRTY_BIT)
+ .value("SelectionButtons_DIRTY_BIT", SelectionButtons_DIRTY_BIT)
+ .value("CitizenButtons_DIRTY_BIT", CitizenButtons_DIRTY_BIT)
+ .value("ResearchButtons_DIRTY_BIT", ResearchButtons_DIRTY_BIT)
+ .value("Event_DIRTY_BIT", Event_DIRTY_BIT)
+ .value("Center_DIRTY_BIT", Center_DIRTY_BIT)
+ .value("GameData_DIRTY_BIT", GameData_DIRTY_BIT)
+ .value("Score_DIRTY_BIT", Score_DIRTY_BIT)
+ .value("TurnTimer_DIRTY_BIT", TurnTimer_DIRTY_BIT)
+ .value("Help_DIRTY_BIT", Help_DIRTY_BIT)
+ .value("MinimapSection_DIRTY_BIT", MinimapSection_DIRTY_BIT)
+ .value("SelectionSound_DIRTY_BIT", SelectionSound_DIRTY_BIT)
+ .value("Cursor_DIRTY_BIT", Cursor_DIRTY_BIT)
+ .value("CityInfo_DIRTY_BIT", CityInfo_DIRTY_BIT)
+ .value("UnitInfo_DIRTY_BIT", UnitInfo_DIRTY_BIT)
+ .value("Popup_DIRTY_BIT", Popup_DIRTY_BIT)
+ .value("CityScreen_DIRTY_BIT", CityScreen_DIRTY_BIT)
+ .value("InfoPane_DIRTY_BIT", InfoPane_DIRTY_BIT)
+ .value("Flag_DIRTY_BIT", Flag_DIRTY_BIT)
+ .value("HighlightPlot_DIRTY_BIT", HighlightPlot_DIRTY_BIT)
+ .value("ColoredPlots_DIRTY_BIT", ColoredPlots_DIRTY_BIT)
+ .value("BlockadedPlots_DIRTY_BIT", BlockadedPlots_DIRTY_BIT)
+ .value("Financial_Screen_DIRTY_BIT", Financial_Screen_DIRTY_BIT)
+ .value("Foreign_Screen_DIRTY_BIT", Foreign_Screen_DIRTY_BIT)
+ .value("Soundtrack_DIRTY_BIT", Soundtrack_DIRTY_BIT)
+ .value("Domestic_Advisor_DIRTY_BIT", Domestic_Advisor_DIRTY_BIT)
+ .value("Espionage_Advisor_DIRTY_BIT", Espionage_Advisor_DIRTY_BIT)
+ .value("Advanced_Start_DIRTY_BIT", Advanced_Start_DIRTY_BIT)
+ .value("NUM_INTERFACE_DIRTY_BITS", NUM_INTERFACE_DIRTY_BITS)
+ ;
+
+ python::enum_("CityTabTypes")
+ .value("CITYTAB_UNITS", CITYTAB_UNITS)
+ .value("CITYTAB_BUILDINGS", CITYTAB_BUILDINGS)
+ .value("CITYTAB_WONDERS", CITYTAB_WONDERS)
+ .value("NUM_CITYTAB_TYPES", NUM_CITYTAB_TYPES)
+ ;
+
+ python::enum_("WidgetTypes")
+ .value("WIDGET_PLOT_LIST", WIDGET_PLOT_LIST)
+ .value("WIDGET_PLOT_LIST_SHIFT", WIDGET_PLOT_LIST_SHIFT)
+ .value("WIDGET_CITY_SCROLL", WIDGET_CITY_SCROLL)
+ .value("WIDGET_LIBERATE_CITY", WIDGET_LIBERATE_CITY)
+ .value("WIDGET_CITY_NAME", WIDGET_CITY_NAME)
+ .value("WIDGET_UNIT_NAME", WIDGET_UNIT_NAME)
+ .value("WIDGET_CREATE_GROUP", WIDGET_CREATE_GROUP)
+ .value("WIDGET_DELETE_GROUP", WIDGET_DELETE_GROUP)
+ .value("WIDGET_TRAIN", WIDGET_TRAIN)
+ .value("WIDGET_CONSTRUCT", WIDGET_CONSTRUCT)
+ .value("WIDGET_CREATE", WIDGET_CREATE)
+ .value("WIDGET_MAINTAIN", WIDGET_MAINTAIN)
+ .value("WIDGET_HURRY", WIDGET_HURRY)
+ .value("WIDGET_MENU_ICON", WIDGET_MENU_ICON)
+ .value("WIDGET_CONSCRIPT", WIDGET_CONSCRIPT)
+ .value("WIDGET_ACTION", WIDGET_ACTION)
+ .value("WIDGET_DISABLED_CITIZEN", WIDGET_DISABLED_CITIZEN)
+ .value("WIDGET_CITIZEN", WIDGET_CITIZEN)
+ .value("WIDGET_FREE_CITIZEN", WIDGET_FREE_CITIZEN)
+ .value("WIDGET_ANGRY_CITIZEN", WIDGET_ANGRY_CITIZEN)
+ .value("WIDGET_CHANGE_SPECIALIST", WIDGET_CHANGE_SPECIALIST)
+ .value("WIDGET_RESEARCH", WIDGET_RESEARCH)
+ .value("WIDGET_TECH_TREE", WIDGET_TECH_TREE)
+ .value("WIDGET_CHANGE_PERCENT", WIDGET_CHANGE_PERCENT)
+ .value("WIDGET_CITY_TAB", WIDGET_CITY_TAB)
+ .value("WIDGET_CONTACT_CIV", WIDGET_CONTACT_CIV)
+ .value("WIDGET_SCORE_BREAKDOWN", WIDGET_SCORE_BREAKDOWN)
+ .value("WIDGET_ZOOM_CITY", WIDGET_ZOOM_CITY)
+ .value("WIDGET_END_TURN", WIDGET_END_TURN)
+ .value("WIDGET_LAUNCH_VICTORY", WIDGET_LAUNCH_VICTORY)
+ .value("WIDGET_CONVERT", WIDGET_CONVERT)
+ .value("WIDGET_WB_SAVE_BUTTON", WIDGET_WB_SAVE_BUTTON)
+ .value("WIDGET_WB_LOAD_BUTTON", WIDGET_WB_LOAD_BUTTON)
+ .value("WIDGET_WB_ALL_PLOTS_BUTTON", WIDGET_WB_ALL_PLOTS_BUTTON)
+ .value("WIDGET_WB_LANDMARK_BUTTON", WIDGET_WB_LANDMARK_BUTTON)
+ .value("WIDGET_WB_ERASE_BUTTON", WIDGET_WB_ERASE_BUTTON)
+ .value("WIDGET_WB_EXIT_BUTTON", WIDGET_WB_EXIT_BUTTON)
+ .value("WIDGET_WB_UNIT_EDIT_BUTTON", WIDGET_WB_UNIT_EDIT_BUTTON)
+ .value("WIDGET_WB_CITY_EDIT_BUTTON", WIDGET_WB_CITY_EDIT_BUTTON)
+ .value("WIDGET_WB_NORMAL_PLAYER_TAB_MODE_BUTTON", WIDGET_WB_NORMAL_PLAYER_TAB_MODE_BUTTON)
+ .value("WIDGET_WB_NORMAL_MAP_TAB_MODE_BUTTON", WIDGET_WB_NORMAL_MAP_TAB_MODE_BUTTON)
+ .value("WIDGET_WB_REVEAL_TAB_MODE_BUTTON", WIDGET_WB_REVEAL_TAB_MODE_BUTTON)
+ .value("WIDGET_WB_DIPLOMACY_MODE_BUTTON", WIDGET_WB_DIPLOMACY_MODE_BUTTON)
+ .value("WIDGET_WB_REVEAL_ALL_BUTTON", WIDGET_WB_REVEAL_ALL_BUTTON)
+ .value("WIDGET_WB_UNREVEAL_ALL_BUTTON", WIDGET_WB_UNREVEAL_ALL_BUTTON)
+ .value("WIDGET_WB_REGENERATE_MAP", WIDGET_WB_REGENERATE_MAP)
+ .value("WIDGET_AUTOMATE_CITIZENS", WIDGET_AUTOMATE_CITIZENS)
+ .value("WIDGET_AUTOMATE_PRODUCTION", WIDGET_AUTOMATE_PRODUCTION)
+ .value("WIDGET_EMPHASIZE", WIDGET_EMPHASIZE)
+ .value("WIDGET_DIPLOMACY_RESPONSE", WIDGET_DIPLOMACY_RESPONSE)
+ .value("WIDGET_GENERAL", WIDGET_GENERAL)
+ .value("WIDGET_FILE_LISTBOX", WIDGET_FILE_LISTBOX)
+ .value("WIDGET_FILE_EDITBOX", WIDGET_FILE_EDITBOX)
+ .value("WIDGET_TRADE_ITEM", WIDGET_TRADE_ITEM)
+ .value("WIDGET_UNIT_MODEL", WIDGET_UNIT_MODEL)
+ .value("WIDGET_FLAG", WIDGET_FLAG)
+ .value("WIDGET_POPUP_QUEUE", WIDGET_POPUP_QUEUE)
+ .value("WIDGET_PYTHON", WIDGET_PYTHON)
+ .value("WIDGET_HELP_MAINTENANCE", WIDGET_HELP_MAINTENANCE)
+ .value("WIDGET_HELP_RELIGION", WIDGET_HELP_RELIGION)
+ .value("WIDGET_HELP_RELIGION_CITY", WIDGET_HELP_RELIGION_CITY)
+ .value("WIDGET_HELP_CORPORATION_CITY", WIDGET_HELP_CORPORATION_CITY)
+ .value("WIDGET_HELP_NATIONALITY", WIDGET_HELP_NATIONALITY)
+ .value("WIDGET_HELP_DEFENSE", WIDGET_HELP_DEFENSE)
+ .value("WIDGET_HELP_HEALTH", WIDGET_HELP_HEALTH)
+ .value("WIDGET_HELP_HAPPINESS", WIDGET_HELP_HAPPINESS)
+ .value("WIDGET_HELP_POPULATION", WIDGET_HELP_POPULATION)
+ .value("WIDGET_HELP_PRODUCTION", WIDGET_HELP_PRODUCTION)
+ .value("WIDGET_HELP_CULTURE", WIDGET_HELP_CULTURE)
+ .value("WIDGET_HELP_GREAT_PEOPLE", WIDGET_HELP_GREAT_PEOPLE)
+ .value("WIDGET_HELP_GREAT_GENERAL", WIDGET_HELP_GREAT_GENERAL)
+ .value("WIDGET_HELP_SELECTED", WIDGET_HELP_SELECTED)
+ .value("WIDGET_HELP_BUILDING", WIDGET_HELP_BUILDING)
+ .value("WIDGET_HELP_TRADE_ROUTE_CITY", WIDGET_HELP_TRADE_ROUTE_CITY)
+ .value("WIDGET_HELP_ESPIONAGE_COST", WIDGET_HELP_ESPIONAGE_COST)
+ .value("WIDGET_HELP_TECH_ENTRY", WIDGET_HELP_TECH_ENTRY)
+ .value("WIDGET_HELP_TECH_PREPREQ", WIDGET_HELP_TECH_PREPREQ)
+ .value("WIDGET_HELP_OBSOLETE", WIDGET_HELP_OBSOLETE)
+ .value("WIDGET_HELP_OBSOLETE_BONUS", WIDGET_HELP_OBSOLETE_BONUS)
+ .value("WIDGET_HELP_OBSOLETE_SPECIAL", WIDGET_HELP_OBSOLETE_SPECIAL)
+ .value("WIDGET_HELP_MOVE_BONUS", WIDGET_HELP_MOVE_BONUS)
+ .value("WIDGET_HELP_FREE_UNIT", WIDGET_HELP_FREE_UNIT)
+ .value("WIDGET_HELP_FEATURE_PRODUCTION", WIDGET_HELP_FEATURE_PRODUCTION)
+ .value("WIDGET_HELP_WORKER_RATE", WIDGET_HELP_WORKER_RATE)
+ .value("WIDGET_HELP_TRADE_ROUTES", WIDGET_HELP_TRADE_ROUTES)
+ .value("WIDGET_HELP_HEALTH_RATE", WIDGET_HELP_HEALTH_RATE)
+ .value("WIDGET_HELP_HAPPINESS_RATE", WIDGET_HELP_HAPPINESS_RATE)
+ .value("WIDGET_HELP_FREE_TECH", WIDGET_HELP_FREE_TECH)
+ .value("WIDGET_HELP_LOS_BONUS", WIDGET_HELP_LOS_BONUS)
+ .value("WIDGET_HELP_MAP_CENTER", WIDGET_HELP_MAP_CENTER)
+ .value("WIDGET_HELP_MAP_REVEAL", WIDGET_HELP_MAP_REVEAL)
+ .value("WIDGET_HELP_MAP_TRADE", WIDGET_HELP_MAP_TRADE)
+ .value("WIDGET_HELP_TECH_TRADE", WIDGET_HELP_TECH_TRADE)
+ .value("WIDGET_HELP_GOLD_TRADE", WIDGET_HELP_GOLD_TRADE)
+ .value("WIDGET_HELP_OPEN_BORDERS", WIDGET_HELP_OPEN_BORDERS)
+ .value("WIDGET_HELP_DEFENSIVE_PACT", WIDGET_HELP_DEFENSIVE_PACT)
+ .value("WIDGET_HELP_PERMANENT_ALLIANCE", WIDGET_HELP_PERMANENT_ALLIANCE)
+ .value("WIDGET_HELP_VASSAL_STATE", WIDGET_HELP_VASSAL_STATE)
+ .value("WIDGET_HELP_BUILD_BRIDGE", WIDGET_HELP_BUILD_BRIDGE)
+ .value("WIDGET_HELP_IRRIGATION", WIDGET_HELP_IRRIGATION)
+ .value("WIDGET_HELP_IGNORE_IRRIGATION", WIDGET_HELP_IGNORE_IRRIGATION)
+ .value("WIDGET_HELP_WATER_WORK", WIDGET_HELP_WATER_WORK)
+ .value("WIDGET_HELP_IMPROVEMENT", WIDGET_HELP_IMPROVEMENT)
+ .value("WIDGET_HELP_DOMAIN_EXTRA_MOVES", WIDGET_HELP_DOMAIN_EXTRA_MOVES)
+ .value("WIDGET_HELP_ADJUST", WIDGET_HELP_ADJUST)
+ .value("WIDGET_HELP_TERRAIN_TRADE", WIDGET_HELP_TERRAIN_TRADE)
+ .value("WIDGET_HELP_SPECIAL_BUILDING", WIDGET_HELP_SPECIAL_BUILDING)
+ .value("WIDGET_HELP_YIELD_CHANGE", WIDGET_HELP_YIELD_CHANGE)
+ .value("WIDGET_HELP_BONUS_REVEAL", WIDGET_HELP_BONUS_REVEAL)
+ .value("WIDGET_HELP_CIVIC_REVEAL", WIDGET_HELP_CIVIC_REVEAL)
+ .value("WIDGET_HELP_PROCESS_INFO", WIDGET_HELP_PROCESS_INFO)
+ .value("WIDGET_HELP_FOUND_RELIGION", WIDGET_HELP_FOUND_RELIGION)
+ .value("WIDGET_HELP_FOUND_CORPORATION", WIDGET_HELP_FOUND_CORPORATION)
+ .value("WIDGET_HELP_FINANCE_NUM_UNITS", WIDGET_HELP_FINANCE_NUM_UNITS)
+ .value("WIDGET_HELP_FINANCE_UNIT_COST", WIDGET_HELP_FINANCE_UNIT_COST)
+ .value("WIDGET_HELP_FINANCE_AWAY_SUPPLY", WIDGET_HELP_FINANCE_AWAY_SUPPLY)
+ .value("WIDGET_HELP_FINANCE_CITY_MAINT", WIDGET_HELP_FINANCE_CITY_MAINT)
+ .value("WIDGET_HELP_FINANCE_CIVIC_UPKEEP", WIDGET_HELP_FINANCE_CIVIC_UPKEEP)
+ .value("WIDGET_HELP_FINANCE_FOREIGN_INCOME", WIDGET_HELP_FINANCE_FOREIGN_INCOME)
+ .value("WIDGET_HELP_FINANCE_INFLATED_COSTS", WIDGET_HELP_FINANCE_INFLATED_COSTS)
+ .value("WIDGET_HELP_FINANCE_GROSS_INCOME", WIDGET_HELP_FINANCE_GROSS_INCOME)
+ .value("WIDGET_HELP_FINANCE_NET_GOLD", WIDGET_HELP_FINANCE_NET_GOLD)
+ .value("WIDGET_HELP_FINANCE_GOLD_RESERVE", WIDGET_HELP_FINANCE_GOLD_RESERVE)
+ .value("WIDGET_HELP_PROMOTION", WIDGET_HELP_PROMOTION)
+ .value("WIDGET_CHOOSE_EVENT", WIDGET_CHOOSE_EVENT)
+ .value("WIDGET_PEDIA_JUMP_TO_TECH", WIDGET_PEDIA_JUMP_TO_TECH)
+ .value("WIDGET_PEDIA_JUMP_TO_UNIT", WIDGET_PEDIA_JUMP_TO_UNIT)
+ .value("WIDGET_PEDIA_JUMP_TO_BUILDING", WIDGET_PEDIA_JUMP_TO_BUILDING)
+ .value("WIDGET_PEDIA_JUMP_TO_DERIVED_TECH", WIDGET_PEDIA_JUMP_TO_DERIVED_TECH)
+ .value("WIDGET_PEDIA_JUMP_TO_REQUIRED_TECH", WIDGET_PEDIA_JUMP_TO_REQUIRED_TECH)
+ .value("WIDGET_PEDIA_BACK", WIDGET_PEDIA_BACK)
+ .value("WIDGET_PEDIA_FORWARD", WIDGET_PEDIA_FORWARD)
+ .value("WIDGET_PEDIA_JUMP_TO_BONUS", WIDGET_PEDIA_JUMP_TO_BONUS)
+ .value("WIDGET_PEDIA_MAIN", WIDGET_PEDIA_MAIN)
+ .value("WIDGET_PEDIA_JUMP_TO_PROMOTION", WIDGET_PEDIA_JUMP_TO_PROMOTION)
+ .value("WIDGET_PEDIA_JUMP_TO_UNIT_COMBAT", WIDGET_PEDIA_JUMP_TO_UNIT_COMBAT)
+ .value("WIDGET_PEDIA_JUMP_TO_IMPROVEMENT", WIDGET_PEDIA_JUMP_TO_IMPROVEMENT)
+ .value("WIDGET_PEDIA_JUMP_TO_CIVIC", WIDGET_PEDIA_JUMP_TO_CIVIC)
+ .value("WIDGET_PEDIA_JUMP_TO_CIV", WIDGET_PEDIA_JUMP_TO_CIV)
+ .value("WIDGET_PEDIA_JUMP_TO_LEADER", WIDGET_PEDIA_JUMP_TO_LEADER)
+ .value("WIDGET_PEDIA_JUMP_TO_SPECIALIST", WIDGET_PEDIA_JUMP_TO_SPECIALIST)
+ .value("WIDGET_PEDIA_JUMP_TO_PROJECT", WIDGET_PEDIA_JUMP_TO_PROJECT)
+ .value("WIDGET_PEDIA_JUMP_TO_TERRAIN", WIDGET_PEDIA_JUMP_TO_TERRAIN)
+ .value("WIDGET_PEDIA_JUMP_TO_FEATURE", WIDGET_PEDIA_JUMP_TO_FEATURE)
+ .value("WIDGET_TURN_EVENT", WIDGET_TURN_EVENT)
+ .value("WIDGET_FOREIGN_ADVISOR", WIDGET_FOREIGN_ADVISOR)
+ .value("WIDGET_REVOLUTION", WIDGET_REVOLUTION)
+ .value("WIDGET_PEDIA_DESCRIPTION", WIDGET_PEDIA_DESCRIPTION)
+ .value("WIDGET_PEDIA_DESCRIPTION_NO_HELP", WIDGET_PEDIA_DESCRIPTION_NO_HELP)
+ .value("WIDGET_DEAL_KILL", WIDGET_DEAL_KILL)
+ .value("WIDGET_MINIMAP_HIGHLIGHT", WIDGET_MINIMAP_HIGHLIGHT)
+ .value("WIDGET_PRODUCTION_MOD_HELP", WIDGET_PRODUCTION_MOD_HELP)
+ .value("WIDGET_LEADERHEAD", WIDGET_LEADERHEAD)
+ .value("WIDGET_LEADER_LINE", WIDGET_LEADER_LINE)
+ .value("WIDGET_COMMERCE_MOD_HELP", WIDGET_COMMERCE_MOD_HELP)
+ .value("WIDGET_CLOSE_SCREEN", WIDGET_CLOSE_SCREEN)
+ .value("WIDGET_PEDIA_JUMP_TO_RELIGION", WIDGET_PEDIA_JUMP_TO_RELIGION)
+ .value("WIDGET_PEDIA_JUMP_TO_CORPORATION", WIDGET_PEDIA_JUMP_TO_CORPORATION)
+ .value("WIDGET_GLOBELAYER", WIDGET_GLOBELAYER)
+ .value("WIDGET_GLOBELAYER_OPTION", WIDGET_GLOBELAYER_OPTION)
+ .value("WIDGET_GLOBELAYER_TOGGLE", WIDGET_GLOBELAYER_TOGGLE)
+
+ .value("NUM_WIDGET_TYPES", NUM_WIDGET_TYPES)
+ ;
+
+ python::enum_("ButtonPopupTypes")
+ .value("BUTTONPOPUP_TEXT", BUTTONPOPUP_TEXT)
+ .value("BUTTONPOPUP_MAIN_MENU", BUTTONPOPUP_MAIN_MENU)
+ .value("BUTTONPOPUP_CONFIRM_MENU", BUTTONPOPUP_CONFIRM_MENU)
+ .value("BUTTONPOPUP_DECLAREWARMOVE", BUTTONPOPUP_DECLAREWARMOVE)
+ .value("BUTTONPOPUP_CONFIRMCOMMAND", BUTTONPOPUP_CONFIRMCOMMAND)
+ .value("BUTTONPOPUP_LOADUNIT", BUTTONPOPUP_LOADUNIT)
+ .value("BUTTONPOPUP_LEADUNIT", BUTTONPOPUP_LEADUNIT)
+ .value("BUTTONPOPUP_DOESPIONAGE", BUTTONPOPUP_DOESPIONAGE)
+ .value("BUTTONPOPUP_DOESPIONAGE_TARGET", BUTTONPOPUP_DOESPIONAGE_TARGET)
+ .value("BUTTONPOPUP_CHOOSETECH", BUTTONPOPUP_CHOOSETECH)
+ .value("BUTTONPOPUP_RAZECITY", BUTTONPOPUP_RAZECITY)
+ .value("BUTTONPOPUP_DISBANDCITY", BUTTONPOPUP_DISBANDCITY)
+ .value("BUTTONPOPUP_CHOOSEPRODUCTION", BUTTONPOPUP_CHOOSEPRODUCTION)
+ .value("BUTTONPOPUP_CHANGECIVIC", BUTTONPOPUP_CHANGECIVIC)
+ .value("BUTTONPOPUP_CHANGERELIGION", BUTTONPOPUP_CHANGERELIGION)
+ .value("BUTTONPOPUP_CHOOSEELECTION", BUTTONPOPUP_CHOOSEELECTION)
+ .value("BUTTONPOPUP_DIPLOVOTE", BUTTONPOPUP_DIPLOVOTE)
+ .value("BUTTONPOPUP_ALARM", BUTTONPOPUP_ALARM)
+ .value("BUTTONPOPUP_DEAL_CANCELED", BUTTONPOPUP_DEAL_CANCELED)
+ .value("BUTTONPOPUP_PYTHON", BUTTONPOPUP_PYTHON)
+ .value("BUTTONPOPUP_PYTHON_SCREEN", BUTTONPOPUP_PYTHON_SCREEN)
+ .value("BUTTONPOPUP_DETAILS", BUTTONPOPUP_DETAILS)
+ .value("BUTTONPOPUP_ADMIN", BUTTONPOPUP_ADMIN)
+ .value("BUTTONPOPUP_ADMIN_PASSWORD", BUTTONPOPUP_ADMIN_PASSWORD)
+ .value("BUTTONPOPUP_EXTENDED_GAME", BUTTONPOPUP_EXTENDED_GAME)
+ .value("BUTTONPOPUP_DIPLOMACY", BUTTONPOPUP_DIPLOMACY)
+ .value("BUTTONPOPUP_ADDBUDDY", BUTTONPOPUP_ADDBUDDY)
+ .value("BUTTONPOPUP_FORCED_DISCONNECT", BUTTONPOPUP_FORCED_DISCONNECT)
+ .value("BUTTONPOPUP_PITBOSS_DISCONNECT", BUTTONPOPUP_PITBOSS_DISCONNECT)
+ .value("BUTTONPOPUP_KICKED", BUTTONPOPUP_PITBOSS_DISCONNECT)
+ .value("BUTTONPOPUP_VASSAL_DEMAND_TRIBUTE", BUTTONPOPUP_VASSAL_DEMAND_TRIBUTE)
+ .value("BUTTONPOPUP_VASSAL_GRANT_TRIBUTE", BUTTONPOPUP_VASSAL_GRANT_TRIBUTE)
+ .value("BUTTONPOPUP_EVENT", BUTTONPOPUP_EVENT)
+ .value("BUTTONPOPUP_FREE_COLONY", BUTTONPOPUP_FREE_COLONY)
+ .value("BUTTONPOPUP_LAUNCH", BUTTONPOPUP_LAUNCH)
+ .value("BUTTONPOPUP_FOUND_RELIGION", BUTTONPOPUP_FOUND_RELIGION)
+
+ .value("NUM_BUTTONPOPUP_TYPES", NUM_BUTTONPOPUP_TYPES)
+ ;
+
+ python::enum_("ClimateTypes")
+ .value("NO_CLIMATE", NO_CLIMATE)
+ ;
+
+ python::enum_("SeaLevelTypes")
+ .value("NO_SEALEVEL", NO_SEALEVEL)
+ ;
+
+ python::enum_("CustomMapOptionTypes")
+ .value("NO_CUSTOM_MAPOPTION", NO_CUSTOM_MAPOPTION)
+ ;
+
+ python::enum_("WorldSizeTypes")
+ .value("NO_WORLDSIZE", NO_WORLDSIZE)
+ .value("WORLDSIZE_DUEL", WORLDSIZE_DUEL)
+ .value("WORLDSIZE_TINY", WORLDSIZE_TINY)
+ .value("WORLDSIZE_SMALL", WORLDSIZE_SMALL)
+ .value("WORLDSIZE_STANDARD", WORLDSIZE_STANDARD)
+ .value("WORLDSIZE_LARGE", WORLDSIZE_LARGE)
+ .value("WORLDSIZE_HUGE", WORLDSIZE_HUGE)
+ .value("NUM_WORLDSIZE_TYPES", NUM_WORLDSIZE_TYPES)
+ ;
+
+ python::enum_("TerrainTypes")
+ .value("NO_TERRAIN", NO_TERRAIN)
+ ;
+
+ python::enum_("PlotTypes")
+ .value("NO_PLOT", NO_PLOT)
+ .value("PLOT_PEAK", PLOT_PEAK)
+ .value("PLOT_HILLS", PLOT_HILLS)
+ .value("PLOT_LAND", PLOT_LAND)
+ .value("PLOT_OCEAN", PLOT_OCEAN)
+ .value("NUM_PLOT_TYPES", NUM_PLOT_TYPES)
+ ;
+
+ python::enum_("YieldTypes")
+ .value("NO_YIELD", NO_YIELD)
+ .value("YIELD_FOOD", YIELD_FOOD)
+ .value("YIELD_PRODUCTION", YIELD_PRODUCTION)
+ .value("YIELD_COMMERCE", YIELD_COMMERCE)
+ .value("NUM_YIELD_TYPES", NUM_YIELD_TYPES)
+ ;
+
+ python::enum_("CommerceTypes")
+ .value("COMMERCE_GOLD", COMMERCE_GOLD)
+ .value("COMMERCE_RESEARCH", COMMERCE_RESEARCH)
+ .value("COMMERCE_CULTURE", COMMERCE_CULTURE)
+ .value("COMMERCE_ESPIONAGE", COMMERCE_ESPIONAGE)
+ .value("NUM_COMMERCE_TYPES", NUM_COMMERCE_TYPES)
+ ;
+
+ python::enum_("AdvisorTypes")
+ .value("NO_ADVISOR", NO_ADVISOR)
+ ;
+
+ python::enum_("FlavorTypes")
+ .value("NO_FLAVOR", NO_FLAVOR)
+ ;
+
+ python::enum_("EmphasizeTypes")
+ .value("NO_EMPHASIZE", NO_EMPHASIZE)
+ ;
+
+ python::enum_("GameOptionTypes")
+ .value("NO_GAMEOPTION", NO_GAMEOPTION)
+ .value("GAMEOPTION_ADVANCED_START", GAMEOPTION_ADVANCED_START)
+ .value("GAMEOPTION_NO_CITY_RAZING", GAMEOPTION_NO_CITY_RAZING)
+ .value("GAMEOPTION_NO_CITY_FLIPPING", GAMEOPTION_NO_CITY_FLIPPING)
+ .value("GAMEOPTION_FLIPPING_AFTER_CONQUEST", GAMEOPTION_FLIPPING_AFTER_CONQUEST)
+ .value("GAMEOPTION_NO_BARBARIANS", GAMEOPTION_NO_BARBARIANS)
+ .value("GAMEOPTION_RAGING_BARBARIANS", GAMEOPTION_RAGING_BARBARIANS)
+ .value("GAMEOPTION_AGGRESSIVE_AI", GAMEOPTION_AGGRESSIVE_AI)
+ .value("GAMEOPTION_LEAD_ANY_CIV", GAMEOPTION_LEAD_ANY_CIV)
+ .value("GAMEOPTION_RANDOM_PERSONALITIES", GAMEOPTION_RANDOM_PERSONALITIES)
+ .value("GAMEOPTION_PICK_RELIGION", GAMEOPTION_PICK_RELIGION)
+ .value("GAMEOPTION_NO_TECH_TRADING", GAMEOPTION_NO_TECH_TRADING)
+ .value("GAMEOPTION_NO_TECH_BROKERING", GAMEOPTION_NO_TECH_BROKERING)
+ .value("GAMEOPTION_PERMANENT_ALLIANCES", GAMEOPTION_PERMANENT_ALLIANCES)
+ .value("GAMEOPTION_ALWAYS_WAR", GAMEOPTION_ALWAYS_WAR)
+ .value("GAMEOPTION_ALWAYS_PEACE", GAMEOPTION_ALWAYS_PEACE)
+ .value("GAMEOPTION_ONE_CITY_CHALLENGE", GAMEOPTION_ONE_CITY_CHALLENGE)
+ .value("GAMEOPTION_NO_CHANGING_WAR_PEACE", GAMEOPTION_NO_CHANGING_WAR_PEACE)
+ .value("GAMEOPTION_NEW_RANDOM_SEED", GAMEOPTION_NEW_RANDOM_SEED)
+ .value("GAMEOPTION_LOCK_MODS", GAMEOPTION_LOCK_MODS)
+ .value("GAMEOPTION_COMPLETE_KILLS", GAMEOPTION_COMPLETE_KILLS)
+ .value("GAMEOPTION_NO_VASSAL_STATES", GAMEOPTION_NO_VASSAL_STATES)
+ .value("GAMEOPTION_NO_GOODY_HUTS", GAMEOPTION_NO_GOODY_HUTS)
+ .value("GAMEOPTION_NO_EVENTS", GAMEOPTION_NO_EVENTS)
+ .value("GAMEOPTION_NO_ESPIONAGE", GAMEOPTION_NO_ESPIONAGE)
+ .value("GAMEOPTION_NO_CITY_TRADING", GAMEOPTION_NO_CITY_TRADING)
+ .value("NUM_GAMEOPTION_TYPES", NUM_GAMEOPTION_TYPES)
+ ;
+
+ python::enum_("MultiplayerOptionTypes")
+ .value("NO_MPOPTION", NO_MPOPTION)
+ .value("MPOPTION_SIMULTANEOUS_TURNS", MPOPTION_SIMULTANEOUS_TURNS)
+ .value("MPOPTION_TAKEOVER_AI", MPOPTION_TAKEOVER_AI)
+ .value("MPOPTION_SHUFFLE_TEAMS", MPOPTION_SHUFFLE_TEAMS)
+ .value("MPOPTION_ANONYMOUS", MPOPTION_ANONYMOUS)
+ .value("MPOPTION_TURN_TIMER", MPOPTION_TURN_TIMER)
+ .value("NUM_MPOPTION_TYPES", NUM_MPOPTION_TYPES)
+ ;
+
+ python::enum_("SpecialOptionTypes")
+ .value("NO_SPECIALOPTION", NO_SPECIALOPTION)
+ .value("SPECIALOPTION_REPORT_STATS", SPECIALOPTION_REPORT_STATS)
+ .value("NUM_SPECIALOPTION_TYPES", NUM_SPECIALOPTION_TYPES)
+ ;
+
+ python::enum_("PlayerOptionTypes")
+ .value("NO_PLAYEROPTION", NO_PLAYEROPTION)
+ .value("PLAYEROPTION_ADVISOR_POPUPS", PLAYEROPTION_ADVISOR_POPUPS)
+ .value("PLAYEROPTION_ADVISOR_HELP", PLAYEROPTION_ADVISOR_HELP)
+ .value("PLAYEROPTION_WAIT_END_TURN", PLAYEROPTION_WAIT_END_TURN)
+ .value("PLAYEROPTION_MINIMIZE_POP_UPS", PLAYEROPTION_MINIMIZE_POP_UPS)
+ .value("PLAYEROPTION_SHOW_FRIENDLY_MOVES", PLAYEROPTION_SHOW_FRIENDLY_MOVES)
+ .value("PLAYEROPTION_SHOW_ENEMY_MOVES", PLAYEROPTION_SHOW_ENEMY_MOVES)
+ .value("PLAYEROPTION_QUICK_MOVES", PLAYEROPTION_QUICK_MOVES)
+ .value("PLAYEROPTION_QUICK_ATTACK", PLAYEROPTION_QUICK_ATTACK)
+ .value("PLAYEROPTION_QUICK_DEFENSE", PLAYEROPTION_QUICK_DEFENSE)
+ .value("PLAYEROPTION_STACK_ATTACK", PLAYEROPTION_STACK_ATTACK)
+ .value("PLAYEROPTION_AUTO_PROMOTION", PLAYEROPTION_AUTO_PROMOTION)
+ .value("PLAYEROPTION_START_AUTOMATED", PLAYEROPTION_START_AUTOMATED)
+ .value("PLAYEROPTION_SAFE_AUTOMATION", PLAYEROPTION_SAFE_AUTOMATION)
+ .value("PLAYEROPTION_NUMPAD_HELP", PLAYEROPTION_NUMPAD_HELP)
+ .value("PLAYEROPTION_NO_UNIT_CYCLING", PLAYEROPTION_NO_UNIT_CYCLING)
+ .value("PLAYEROPTION_NO_UNIT_RECOMMENDATIONS", PLAYEROPTION_NO_UNIT_RECOMMENDATIONS)
+ .value("PLAYEROPTION_RIGHT_CLICK_MENU", PLAYEROPTION_RIGHT_CLICK_MENU)
+ .value("PLAYEROPTION_LEAVE_FORESTS", PLAYEROPTION_LEAVE_FORESTS)
+ .value("PLAYEROPTION_MISSIONARIES_AUTOMATED", PLAYEROPTION_MISSIONARIES_AUTOMATED)
+ .value("PLAYEROPTION_MODDER_1", PLAYEROPTION_MODDER_1)
+ .value("PLAYEROPTION_MODDER_2", PLAYEROPTION_MODDER_2)
+ .value("PLAYEROPTION_MODDER_3", PLAYEROPTION_MODDER_3)
+ .value("NUM_PLAYEROPTION_TYPES", NUM_PLAYEROPTION_TYPES)
+ ;
+
+ python::enum_("GraphicOptionTypes")
+ .value("NO_GRAPHICOPTION", NO_GRAPHICOPTION)
+ .value("GRAPHICOPTION_SINGLE_UNIT_GRAPHICS", GRAPHICOPTION_SINGLE_UNIT_GRAPHICS)
+ .value("GRAPHICOPTION_HEALTH_BARS", GRAPHICOPTION_HEALTH_BARS)
+ .value("GRAPHICOPTION_CITY_DETAIL", GRAPHICOPTION_CITY_DETAIL)
+ .value("GRAPHICOPTION_NO_COMBAT_ZOOM", GRAPHICOPTION_NO_COMBAT_ZOOM)
+ .value("GRAPHICOPTION_NO_ENEMY_GLOW", GRAPHICOPTION_NO_ENEMY_GLOW)
+ .value("GRAPHICOPTION_FROZEN_ANIMATIONS", GRAPHICOPTION_FROZEN_ANIMATIONS)
+ .value("GRAPHICOPTION_EFFECTS_DISABLED", GRAPHICOPTION_EFFECTS_DISABLED)
+ .value("GRAPHICOPTION_GLOBE_VIEW_BUILDINGS_DISABLED", GRAPHICOPTION_GLOBE_VIEW_BUILDINGS_DISABLED)
+ .value("GRAPHICOPTION_FULLSCREEN", GRAPHICOPTION_FULLSCREEN)
+ .value("GRAPHICOPTION_LOWRES_TEXTURES", GRAPHICOPTION_LOWRES_TEXTURES)
+ .value("GRAPHICOPTION_HIRES_TERRAIN", GRAPHICOPTION_HIRES_TERRAIN)
+ .value("GRAPHICOPTION_NO_MOVIES", GRAPHICOPTION_NO_MOVIES)
+ .value("GRAPHICOPTION_CITY_RADIUS", GRAPHICOPTION_CITY_RADIUS)
+ .value("NUM_GRAPHICOPTION_TYPES", NUM_GRAPHICOPTION_TYPES)
+ ;
+
+ python::enum_("ForceControlTypes")
+ .value("NO_FORCECONTROL", NO_FORCECONTROL)
+ .value("FORCECONTROL_SPEED", FORCECONTROL_SPEED)
+ .value("FORCECONTROL_HANDICAP", FORCECONTROL_HANDICAP)
+ .value("FORCECONTROL_OPTIONS", FORCECONTROL_OPTIONS)
+ .value("FORCECONTROL_VICTORIES", FORCECONTROL_VICTORIES)
+ .value("FORCECONTROL_MAX_TURNS", FORCECONTROL_MAX_TURNS)
+ .value("FORCECONTROL_MAX_CITY_ELIMINATIONS", FORCECONTROL_MAX_CITY_ELIMINATION)
+ .value("FORCECONTROL_ADVANCED_START", FORCECONTROL_ADVANCED_START)
+ .value("NUM_FORCECONTROL_TYPES", NUM_FORCECONTROL_TYPES)
+ ;
+
+ python::enum_("VictoryTypes")
+ .value("NO_VICTORY", NO_VICTORY)
+ ;
+
+ python::enum_("FeatureTypes")
+ .value("NO_FEATURE", NO_FEATURE)
+ ;
+
+ python::enum_("BonusTypes")
+ .value("NO_BONUS", NO_BONUS)
+ ;
+
+ python::enum_("BonusClassTypes")
+ .value("NO_BONUSCLASS", NO_BONUSCLASS)
+ ;
+
+ python::enum_("ImprovementTypes")
+ .value("NO_IMPROVEMENT", NO_IMPROVEMENT)
+ ;
+
+ python::enum_("RouteTypes")
+ .value("NO_ROUTE", NO_ROUTE)
+ ;
+
+ python::enum_("RiverTypes")
+ .value("NO_RIVER", NO_RIVER)
+ ;
+
+ python::enum_("GoodyTypes")
+ .value("NO_GOODY", NO_GOODY)
+ ;
+
+ python::enum_("BuildTypes")
+ .value("NO_BUILD", NO_BUILD)
+ ;
+
+ python::enum_("SymbolTypes")
+ .value("NO_SYMBOL", NO_SYMBOL)
+ ;
+
+ python::enum_("FontSymbols")
+ .value("HAPPY_CHAR", HAPPY_CHAR)
+ .value("UNHAPPY_CHAR", UNHAPPY_CHAR)
+ .value("HEALTHY_CHAR", HEALTHY_CHAR)
+ .value("UNHEALTHY_CHAR", UNHEALTHY_CHAR)
+ .value("BULLET_CHAR", BULLET_CHAR)
+ .value("STRENGTH_CHAR", STRENGTH_CHAR)
+ .value("MOVES_CHAR", MOVES_CHAR)
+ .value("RELIGION_CHAR", RELIGION_CHAR)
+ .value("STAR_CHAR", STAR_CHAR)
+ .value("SILVER_STAR_CHAR", SILVER_STAR_CHAR)
+ .value("TRADE_CHAR", TRADE_CHAR)
+ .value("DEFENSE_CHAR", DEFENSE_CHAR)
+ .value("GREAT_PEOPLE_CHAR", GREAT_PEOPLE_CHAR)
+ .value("BAD_GOLD_CHAR", BAD_GOLD_CHAR)
+ .value("BAD_FOOD_CHAR", BAD_FOOD_CHAR)
+ .value("EATEN_FOOD_CHAR", EATEN_FOOD_CHAR)
+ .value("GOLDEN_AGE_CHAR", GOLDEN_AGE_CHAR)
+ .value("ANGRY_POP_CHAR", ANGRY_POP_CHAR)
+ .value("OPEN_BORDERS_CHAR", OPEN_BORDERS_CHAR)
+ .value("DEFENSIVE_PACT_CHAR", DEFENSIVE_PACT_CHAR)
+ .value("MAP_CHAR", MAP_CHAR)
+ .value("OCCUPATION_CHAR", OCCUPATION_CHAR)
+ .value("POWER_CHAR", POWER_CHAR)
+ .value("MAX_NUM_SYMBOLS", MAX_NUM_SYMBOLS)
+ ;
+
+ python::enum_("HandicapTypes")
+ .value("NO_HANDICAP", NO_HANDICAP)
+ ;
+
+ python::enum_("GameSpeedTypes")
+ .value("NO_GAMESPEED", NO_GAMESPEED)
+ ;
+
+ python::enum_("TurnTimerTypes")
+ .value("NO_TURNTIMER", NO_TURNTIMER)
+ ;
+
+ python::enum_("EraTypes")
+ .value("NO_ERA", NO_ERA)
+ ;
+
+ python::enum_("CivilizationTypes")
+ .value("NO_CIVILIZATION", NO_CIVILIZATION)
+ ;
+
+ python::enum_("LeaderHeadTypes")
+ .value("NO_LEADER", NO_LEADER)
+ ;
+
+ python::enum_("ArtStyleTypes")
+ .value("NO_ARTSTYLE", NO_ARTSTYLE)
+ ;
+
+ python::enum_("CitySizeTypes")
+ .value("NO_CITYSIZE", NO_CITYSIZE)
+ .value("CITYSIZE_SMALL", CITYSIZE_SMALL)
+ .value("CITYSIZE_MEDIUM", CITYSIZE_MEDIUM)
+ .value("CITYSIZE_LARGE", CITYSIZE_LARGE)
+ .value("NUM_CITYSIZE_TYPES", NUM_CITYSIZE_TYPES)
+ ;
+
+ python::enum_("FootstepAudioTypes")
+ .value("NO_FOOTSTEPAUDIO", NO_FOOTSTEPAUDIO)
+ ;
+
+ python::enum_("FootstepAudioTags")
+ .value("NO_FOOTSTEPAUDIO_TAG", NO_FOOTSTEPAUDIO_TAG)
+ ;
+
+ python::enum_("ChatTargetTypes")
+ .value("NO_CHATTARGET", NO_CHATTARGET)
+ .value("CHATTARGET_ALL", CHATTARGET_ALL)
+ .value("CHATTARGET_TEAM", CHATTARGET_TEAM)
+ ;
+
+ python::enum_("VoiceTargetTypes")
+ .value("NO_VOICETARGET", NO_VOICETARGET)
+ .value("VOICETARGET_DIPLO", VOICETARGET_DIPLO)
+ .value("VOICETARGET_TEAM", VOICETARGET_TEAM)
+ .value("VOICETARGET_ALL", VOICETARGET_ALL)
+ .value("NUM_VOICETARGETS", NUM_VOICETARGETS)
+ ;
+
+ python::enum_("TeamTypes")
+ .value("NO_TEAM", NO_TEAM)
+ ;
+
+ python::enum_("PlayerTypes")
+ .value("NO_PLAYER", NO_PLAYER)
+ ;
+
+ python::enum_("TraitTypes")
+ .value("NO_TRAIT", NO_TRAIT)
+ ;
+
+ python::enum_("OrderTypes")
+ .value("NO_ORDER", NO_ORDER)
+ .value("ORDER_TRAIN", ORDER_TRAIN)
+ .value("ORDER_CONSTRUCT", ORDER_CONSTRUCT)
+ .value("ORDER_CREATE", ORDER_CREATE)
+ .value("ORDER_MAINTAIN", ORDER_MAINTAIN)
+ .value("NUM_ORDER_TYPES", NUM_ORDER_TYPES)
+ ;
+
+ python::enum_("TaskTypes")
+ .value("TASK_RAZE", TASK_RAZE)
+ .value("TASK_DISBAND", TASK_DISBAND)
+ .value("TASK_GIFT", TASK_GIFT)
+ .value("TASK_SET_AUTOMATED_CITIZENS", TASK_SET_AUTOMATED_CITIZENS)
+ .value("TASK_SET_AUTOMATED_PRODUCTION", TASK_SET_AUTOMATED_PRODUCTION)
+ .value("TASK_SET_EMPHASIZE", TASK_SET_EMPHASIZE)
+ .value("TASK_CHANGE_SPECIALIST", TASK_CHANGE_SPECIALIST)
+ .value("TASK_CHANGE_WORKING_PLOT", TASK_CHANGE_WORKING_PLOT)
+ .value("TASK_CLEAR_WORKING_OVERRIDE", TASK_CLEAR_WORKING_OVERRIDE)
+ .value("TASK_HURRY", TASK_HURRY)
+ .value("TASK_CONSCRIPT", TASK_HURRY)
+ .value("TASK_CLEAR_ORDERS", TASK_CLEAR_ORDERS)
+ .value("TASK_RALLY_PLOT", TASK_RALLY_PLOT)
+ .value("TASK_CLEAR_RALLY_PLOT", TASK_CLEAR_RALLY_PLOT)
+ .value("TASK_LIBERATE", TASK_LIBERATE)
+ .value("NUM_TASK_TYPES", NUM_TASK_TYPES)
+ ;
+
+ python::enum_("BuildingClassTypes")
+ .value("NO_BUILDINGCLASS", NO_BUILDINGCLASS)
+ ;
+
+ python::enum_("BuildingTypes")
+ .value("NO_BUILDING", NO_BUILDING)
+ ;
+
+ python::enum_("SpecialBuildingTypes")
+ .value("NO_SPECIALBUILDING", NO_SPECIALBUILDING)
+ ;
+
+ python::enum_("ProjectTypes")
+ .value("NO_PROJECT", NO_PROJECT)
+ ;
+
+ python::enum_("ProcessTypes")
+ .value("NO_PROCESS", NO_PROCESS)
+ ;
+
+ python::enum_("VoteTypes")
+ .value("NO_VOTE", NO_VOTE)
+ ;
+
+ python::enum_("PlayerVoteTypes")
+ .value("NO_PLAYER_VOTE_CHECKED", NO_PLAYER_VOTE_CHECKED)
+ .value("PLAYER_VOTE_NEVER", PLAYER_VOTE_NEVER)
+ .value("PLAYER_VOTE_ABSTAIN", PLAYER_VOTE_ABSTAIN)
+ .value("PLAYER_VOTE_NO", PLAYER_VOTE_NO)
+ .value("PLAYER_VOTE_YES", PLAYER_VOTE_YES)
+ .value("NO_PLAYER_VOTE", NO_PLAYER_VOTE)
+ ;
+
+ python::enum_("InfoBarTypes")
+ .value("INFOBAR_STORED", INFOBAR_STORED)
+ .value("INFOBAR_RATE", INFOBAR_RATE)
+ .value("INFOBAR_RATE_EXTRA", INFOBAR_RATE_EXTRA)
+ .value("INFOBAR_EMPTY", INFOBAR_EMPTY)
+ .value("NUM_INFOBAR_TYPES", NUM_INFOBAR_TYPES)
+ ;
+
+ python::enum_("HealthBarTypes")
+ .value("HEALTHBAR_ALIVE_ATTACK", HEALTHBAR_ALIVE_ATTACK)
+ .value("HEALTHBAR_ALIVE_DEFEND", HEALTHBAR_ALIVE_DEFEND)
+ .value("HEALTHBAR_DEAD", HEALTHBAR_DEAD)
+ .value("NUM_HEALTHBAR_TYPES", NUM_HEALTHBAR_TYPES)
+ ;
+
+ python::enum_("ConceptTypes")
+ .value("NO_CONCEPT", NO_CONCEPT)
+ ;
+
+ python::enum_("NewConceptTypes")
+ .value("NO_NEW_CONCEPT", NO_NEW_CONCEPT)
+ ;
+
+ python::enum_("CalendarTypes")
+ .value("CALENDAR_DEFAULT", CALENDAR_DEFAULT)
+ .value("CALENDAR_BI_YEARLY", CALENDAR_BI_YEARLY)
+ .value("CALENDAR_YEARS", CALENDAR_YEARS)
+ .value("CALENDAR_TURNS", CALENDAR_TURNS)
+ .value("CALENDAR_SEASONS", CALENDAR_SEASONS)
+ .value("CALENDAR_MONTHS", CALENDAR_MONTHS)
+ .value("CALENDAR_WEEKS", CALENDAR_WEEKS)
+ ;
+
+ python::enum_("SeasonTypes")
+ .value("NO_SEASON", NO_SEASON)
+ ;
+
+ python::enum_("MonthTypes")
+ .value("NO_MONTH", NO_MONTH)
+ ;
+
+ python::enum_("DenialTypes")
+ .value("NO_DENIAL", NO_DENIAL)
+ .value("DENIAL_UNKNOWN", DENIAL_UNKNOWN)
+ .value("DENIAL_NEVER", DENIAL_NEVER)
+ .value("DENIAL_TOO_MUCH", DENIAL_TOO_MUCH)
+ .value("DENIAL_MYSTERY", DENIAL_MYSTERY)
+ .value("DENIAL_JOKING", DENIAL_JOKING)
+ .value("DENIAL_ANGER_CIVIC", DENIAL_ANGER_CIVIC)
+ .value("DENIAL_FAVORITE_CIVIC", DENIAL_FAVORITE_CIVIC)
+ .value("DENIAL_MINORITY_RELIGION", DENIAL_MINORITY_RELIGION)
+ .value("DENIAL_CONTACT_THEM", DENIAL_CONTACT_THEM)
+ .value("DENIAL_VICTORY", DENIAL_VICTORY)
+ .value("DENIAL_ATTITUDE", DENIAL_ATTITUDE)
+ .value("DENIAL_ATTITUDE_THEM", DENIAL_ATTITUDE_THEM)
+ .value("DENIAL_TECH_WHORE", DENIAL_TECH_WHORE)
+ .value("DENIAL_TECH_MONOPOLY", DENIAL_TECH_MONOPOLY)
+ .value("DENIAL_POWER_US", DENIAL_POWER_US)
+ .value("DENIAL_POWER_YOU", DENIAL_POWER_YOU)
+ .value("DENIAL_POWER_THEM", DENIAL_POWER_THEM)
+ .value("DENIAL_TOO_MANY_WARS", DENIAL_TOO_MANY_WARS)
+ .value("DENIAL_NO_GAIN", DENIAL_NO_GAIN)
+ .value("DENIAL_NOT_ALLIED", DENIAL_NOT_ALLIED)
+ .value("DENIAL_RECENT_CANCEL", DENIAL_RECENT_CANCEL)
+ .value("DENIAL_WORST_ENEMY", DENIAL_WORST_ENEMY)
+ .value("DENIAL_POWER_YOUR_ENEMIES", DENIAL_POWER_YOUR_ENEMIES)
+ .value("DENIAL_TOO_FAR", DENIAL_TOO_FAR)
+ ;
+
+ python::enum_("DomainTypes")
+ .value("DOMAIN_SEA", DOMAIN_SEA)
+ .value("DOMAIN_AIR", DOMAIN_AIR)
+ .value("DOMAIN_LAND", DOMAIN_LAND)
+ .value("DOMAIN_IMMOBILE", DOMAIN_IMMOBILE)
+ .value("NUM_DOMAIN_TYPES", NUM_DOMAIN_TYPES)
+ ;
+
+ python::enum_("UnitClassTypes")
+ .value("NO_UNITCLASS", NO_UNITCLASS)
+ ;
+
+ python::enum_("UnitTypes")
+ .value("NO_UNIT", NO_UNIT)
+ ;
+
+ python::enum_("SpecialUnitTypes")
+ .value("NO_SPECIALUNIT", NO_SPECIALUNIT)
+ ;
+
+ python::enum_("UnitCombatTypes")
+ .value("NO_UNITCOMBAT", NO_UNITCOMBAT)
+ ;
+
+ python::enum_("UnitAITypes")
+ .value("NO_UNITAI", NO_UNITAI)
+ .value("UNITAI_UNKNOWN", UNITAI_UNKNOWN)
+ .value("UNITAI_ANIMAL", UNITAI_ANIMAL)
+ .value("UNITAI_SETTLE", UNITAI_SETTLE)
+ .value("UNITAI_WORKER", UNITAI_WORKER)
+ .value("UNITAI_ATTACK", UNITAI_ATTACK)
+ .value("UNITAI_ATTACK_CITY", UNITAI_ATTACK_CITY)
+ .value("UNITAI_COLLATERAL", UNITAI_COLLATERAL)
+ .value("UNITAI_PILLAGE", UNITAI_PILLAGE)
+ .value("UNITAI_RESERVE", UNITAI_RESERVE)
+ .value("UNITAI_COUNTER", UNITAI_COUNTER)
+ .value("UNITAI_CITY_DEFENSE", UNITAI_CITY_DEFENSE)
+ .value("UNITAI_CITY_COUNTER", UNITAI_CITY_COUNTER)
+ .value("UNITAI_CITY_SPECIAL", UNITAI_CITY_SPECIAL)
+ .value("UNITAI_EXPLORE", UNITAI_EXPLORE)
+ .value("UNITAI_MISSIONARY", UNITAI_MISSIONARY)
+ .value("UNITAI_PROPHET", UNITAI_PROPHET)
+ .value("UNITAI_ARTIST", UNITAI_ARTIST)
+ .value("UNITAI_SCIENTIST", UNITAI_SCIENTIST)
+ .value("UNITAI_GENERAL", UNITAI_GENERAL)
+ .value("UNITAI_MERCHANT", UNITAI_MERCHANT)
+ .value("UNITAI_ENGINEER", UNITAI_ENGINEER)
+ .value("UNITAI_SPY", UNITAI_SPY)
+ .value("UNITAI_ICBM", UNITAI_ICBM)
+ .value("UNITAI_WORKER_SEA", UNITAI_WORKER_SEA)
+ .value("UNITAI_ATTACK_SEA", UNITAI_ATTACK_SEA)
+ .value("UNITAI_RESERVE_SEA", UNITAI_RESERVE_SEA)
+ .value("UNITAI_ESCORT_SEA", UNITAI_ESCORT_SEA)
+ .value("UNITAI_EXPLORE_SEA", UNITAI_EXPLORE_SEA)
+ .value("UNITAI_ASSAULT_SEA", UNITAI_ASSAULT_SEA)
+ .value("UNITAI_SETTLER_SEA", UNITAI_SETTLER_SEA)
+ .value("UNITAI_MISSIONARY_SEA", UNITAI_MISSIONARY_SEA)
+ .value("UNITAI_SPY_SEA", UNITAI_SPY_SEA)
+ .value("UNITAI_CARRIER_SEA", UNITAI_CARRIER_SEA)
+ .value("UNITAI_MISSILE_CARRIER_SEA", UNITAI_MISSILE_CARRIER_SEA)
+ .value("UNITAI_PIRATE_SEA", UNITAI_PIRATE_SEA)
+ .value("UNITAI_ATTACK_AIR", UNITAI_ATTACK_AIR)
+ .value("UNITAI_DEFENSE_AIR", UNITAI_DEFENSE_AIR)
+ .value("UNITAI_CARRIER_AIR", UNITAI_CARRIER_AIR)
+ .value("UNITAI_MISSILE_AIR", UNITAI_MISSILE_AIR)
+ .value("UNITAI_PARADROP", UNITAI_PARADROP)
+ .value("UNITAI_ATTACK_CITY_LEMMING", UNITAI_ATTACK_CITY_LEMMING)
+ .value("NUM_UNITAI_TYPES", NUM_UNITAI_TYPES)
+ ;
+
+ python::enum_("InvisibleTypes")
+ .value("NO_INVISIBLE", NO_INVISIBLE)
+ ;
+
+ python::enum_("VoteSourceTypes")
+ .value("NO_VOTESOURCE", NO_VOTESOURCE)
+ ;
+
+ python::enum_("ProbabilityTypes")
+ .value("NO_PROBABILITY", NO_PROBABILITY)
+ .value("PROBABILITY_LOW", PROBABILITY_LOW)
+ .value("PROBABILITY_REAL", PROBABILITY_REAL)
+ .value("PROBABILITY_HIGH", PROBABILITY_HIGH)
+ ;
+
+ python::enum_("ActivityTypes")
+ .value("NO_ACTIVITY", NO_ACTIVITY)
+ .value("ACTIVITY_AWAKE", ACTIVITY_AWAKE)
+ .value("ACTIVITY_HOLD", ACTIVITY_HOLD)
+ .value("ACTIVITY_SLEEP", ACTIVITY_SLEEP)
+ .value("ACTIVITY_HEAL", ACTIVITY_HEAL)
+ .value("ACTIVITY_SENTRY", ACTIVITY_SENTRY)
+ .value("ACTIVITY_INTERCEPT", ACTIVITY_INTERCEPT)
+ .value("ACTIVITY_MISSION", ACTIVITY_MISSION)
+ .value("ACTIVITY_PATROL", ACTIVITY_PATROL)
+ .value("ACTIVITY_PLUNDER", ACTIVITY_PLUNDER)
+ .value("NUM_ACTIVITY_TYPES", NUM_ACTIVITY_TYPES)
+ ;
+
+ python::enum_("AutomateTypes")
+ .value("NO_AUTOMATE", NO_AUTOMATE)
+ .value("AUTOMATE_BUILD", AUTOMATE_BUILD)
+ .value("AUTOMATE_NETWORK", AUTOMATE_NETWORK)
+ .value("AUTOMATE_CITY", AUTOMATE_CITY)
+ .value("AUTOMATE_EXPLORE", AUTOMATE_EXPLORE)
+ .value("AUTOMATE_RELIGION", AUTOMATE_RELIGION)
+ .value("NUM_AUTOMATE_TYPES", NUM_AUTOMATE_TYPES)
+ ;
+
+ python::enum_("MissionTypes")
+ .value("NO_MISSION", NO_MISSION)
+ .value("MISSION_MOVE_TO", MISSION_MOVE_TO)
+ .value("MISSION_ROUTE_TO", MISSION_ROUTE_TO)
+ .value("MISSION_MOVE_TO_UNIT", MISSION_MOVE_TO_UNIT)
+ .value("MISSION_SKIP", MISSION_SKIP)
+ .value("MISSION_SLEEP", MISSION_SLEEP)
+ .value("MISSION_FORTIFY", MISSION_FORTIFY)
+ .value("MISSION_PLUNDER", MISSION_PLUNDER)
+ .value("MISSION_AIRPATROL", MISSION_AIRPATROL)
+ .value("MISSION_SEAPATROL", MISSION_SEAPATROL)
+ .value("MISSION_HEAL", MISSION_HEAL)
+ .value("MISSION_SENTRY", MISSION_SENTRY)
+ .value("MISSION_AIRLIFT", MISSION_AIRLIFT)
+ .value("MISSION_NUKE", MISSION_NUKE)
+ .value("MISSION_RECON", MISSION_RECON)
+ .value("MISSION_PARADROP", MISSION_PARADROP)
+ .value("MISSION_AIRBOMB", MISSION_AIRBOMB)
+ .value("MISSION_RANGE_ATTACK", MISSION_RANGE_ATTACK)
+ .value("MISSION_BOMBARD", MISSION_BOMBARD)
+ .value("MISSION_PILLAGE", MISSION_PILLAGE)
+ .value("MISSION_SABOTAGE", MISSION_SABOTAGE)
+ .value("MISSION_DESTROY", MISSION_DESTROY)
+ .value("MISSION_STEAL_PLANS", MISSION_STEAL_PLANS)
+ .value("MISSION_FOUND", MISSION_FOUND)
+ .value("MISSION_SPREAD", MISSION_SPREAD)
+ .value("MISSION_SPREAD_CORPORATION", MISSION_SPREAD_CORPORATION)
+ .value("MISSION_JOIN", MISSION_JOIN)
+ .value("MISSION_CONSTRUCT", MISSION_CONSTRUCT)
+ .value("MISSION_DISCOVER", MISSION_DISCOVER)
+ .value("MISSION_HURRY", MISSION_HURRY)
+ .value("MISSION_TRADE", MISSION_TRADE)
+ .value("MISSION_GREAT_WORK", MISSION_GREAT_WORK)
+ .value("MISSION_INFILTRATE", MISSION_INFILTRATE)
+ .value("MISSION_LEAD", MISSION_LEAD)
+ .value("MISSION_ESPIONAGE", MISSION_ESPIONAGE)
+ .value("MISSION_GOLDEN_AGE", MISSION_GOLDEN_AGE)
+ .value("MISSION_BUILD", MISSION_BUILD)
+ .value("MISSION_BEGIN_COMBAT", MISSION_BEGIN_COMBAT )
+ .value("MISSION_END_COMBAT", MISSION_END_COMBAT )
+ .value("MISSION_AIRSTRIKE", MISSION_AIRSTRIKE )
+ .value("MISSION_SURRENDER", MISSION_SURRENDER )
+ .value("MISSION_CAPTURED", MISSION_CAPTURED )
+ .value("MISSION_IDLE", MISSION_IDLE )
+ .value("MISSION_DIE", MISSION_DIE )
+ .value("MISSION_DAMAGE", MISSION_DAMAGE )
+ .value("MISSION_MULTI_SELECT", MISSION_MULTI_SELECT )
+ .value("MISSION_MULTI_DESELECT", MISSION_MULTI_DESELECT )
+ .value("NUM_MISSION_TYPES", NUM_MISSION_TYPES )
+ ;
+
+ python::enum_("MissionAITypes")
+ .value("NO_MISSIONAI", NO_MISSIONAI)
+ .value("MISSIONAI_SHADOW", MISSIONAI_SHADOW)
+ .value("MISSIONAI_GROUP", MISSIONAI_GROUP)
+ .value("MISSIONAI_LOAD_ASSAULT", MISSIONAI_LOAD_ASSAULT)
+ .value("MISSIONAI_LOAD_SETTLER", MISSIONAI_LOAD_SETTLER)
+ .value("MISSIONAI_LOAD_SPECIAL", MISSIONAI_LOAD_SPECIAL)
+ .value("MISSIONAI_GUARD_CITY", MISSIONAI_GUARD_CITY)
+ .value("MISSIONAI_GUARD_BONUS", MISSIONAI_GUARD_BONUS)
+ .value("MISSIONAI_GUARD_TRADE_NET", MISSIONAI_GUARD_TRADE_NET)
+ .value("MISSIONAI_GUARD_SPY", MISSIONAI_GUARD_SPY)
+ .value("MISSIONAI_ATTACK_SPY", MISSIONAI_ATTACK_SPY)
+ .value("MISSIONAI_SPREAD", MISSIONAI_SPREAD)
+ .value("MISSIONAI_SPREAD_CORPORATION", MISSIONAI_SPREAD_CORPORATION)
+ .value("MISSIONAI_CONSTRUCT", MISSIONAI_CONSTRUCT)
+ .value("MISSIONAI_HURRY", MISSIONAI_HURRY)
+ .value("MISSIONAI_GREAT_WORK", MISSIONAI_GREAT_WORK)
+ .value("MISSIONAI_EXPLORE", MISSIONAI_EXPLORE)
+ .value("MISSIONAI_BLOCKADE", MISSIONAI_BLOCKADE)
+ .value("MISSIONAI_PILLAGE", MISSIONAI_PILLAGE)
+ .value("MISSIONAI_FOUND", MISSIONAI_FOUND)
+ .value("MISSIONAI_BUILD", MISSIONAI_BUILD)
+ .value("MISSIONAI_ASSAULT", MISSIONAI_ASSAULT)
+ .value("MISSIONAI_CARRIER", MISSIONAI_CARRIER)
+ .value("MISSIONAI_PICKUP", MISSIONAI_PICKUP)
+ ;
+
+ // any additions need to be reflected in GlobalTypes.xml
+ python::enum_("CommandTypes")
+ .value("NO_COMMAND", NO_COMMAND)
+ .value("COMMAND_PROMOTION", COMMAND_PROMOTION)
+ .value("COMMAND_UPGRADE", COMMAND_UPGRADE)
+ .value("COMMAND_AUTOMATE", COMMAND_AUTOMATE)
+ .value("COMMAND_WAKE", COMMAND_WAKE)
+ .value("COMMAND_CANCEL", COMMAND_CANCEL)
+ .value("COMMAND_CANCEL_ALL", COMMAND_CANCEL_ALL)
+ .value("COMMAND_STOP_AUTOMATION", COMMAND_STOP_AUTOMATION)
+ .value("COMMAND_DELETE", COMMAND_DELETE)
+ .value("COMMAND_GIFT", COMMAND_GIFT)
+ .value("COMMAND_LOAD", COMMAND_LOAD)
+ .value("COMMAND_LOAD_UNIT", COMMAND_LOAD_UNIT)
+ .value("COMMAND_UNLOAD", COMMAND_UNLOAD)
+ .value("COMMAND_UNLOAD_ALL", COMMAND_UNLOAD_ALL)
+ .value("COMMAND_HOTKEY", COMMAND_HOTKEY)
+ .value("NUM_COMMAND_TYPES", NUM_COMMAND_TYPES)
+ ;
+
+ python::enum_("ControlTypes")
+ .value("NO_CONTROL", NO_CONTROL)
+ .value("CONTROL_CENTERONSELECTION", CONTROL_CENTERONSELECTION)
+ .value("CONTROL_SELECTYUNITTYPE", CONTROL_SELECTYUNITTYPE)
+ .value("CONTROL_SELECTYUNITALL", CONTROL_SELECTYUNITALL)
+ .value("CONTROL_SELECTCITY", CONTROL_SELECTCITY)
+ .value("CONTROL_SELECTCAPITAL", CONTROL_SELECTCAPITAL)
+ .value("CONTROL_NEXTCITY", CONTROL_NEXTCITY)
+ .value("CONTROL_PREVCITY", CONTROL_PREVCITY)
+ .value("CONTROL_NEXTUNIT", CONTROL_NEXTUNIT)
+ .value("CONTROL_PREVUNIT", CONTROL_PREVUNIT)
+ .value("CONTROL_CYCLEUNIT", CONTROL_CYCLEUNIT)
+ .value("CONTROL_CYCLEUNIT_ALT", CONTROL_CYCLEUNIT_ALT)
+ .value("CONTROL_CYCLEWORKER", CONTROL_CYCLEWORKER)
+ .value("CONTROL_LASTUNIT", CONTROL_LASTUNIT)
+ .value("CONTROL_ENDTURN", CONTROL_ENDTURN)
+ .value("CONTROL_ENDTURN_ALT", CONTROL_ENDTURN_ALT)
+ .value("CONTROL_FORCEENDTURN", CONTROL_FORCEENDTURN)
+ .value("CONTROL_AUTOMOVES", CONTROL_AUTOMOVES)
+ .value("CONTROL_PING", CONTROL_PING)
+ .value("CONTROL_SIGN", CONTROL_SIGN)
+ .value("CONTROL_GRID", CONTROL_GRID)
+ .value("CONTROL_BARE_MAP", CONTROL_BARE_MAP)
+ .value("CONTROL_YIELDS", CONTROL_YIELDS)
+ .value("CONTROL_RESOURCE_ALL", CONTROL_RESOURCE_ALL)
+ .value("CONTROL_UNIT_ICONS", CONTROL_UNIT_ICONS)
+ .value("CONTROL_GLOBELAYER", CONTROL_GLOBELAYER)
+ .value("CONTROL_SCORES", CONTROL_SCORES)
+ .value("CONTROL_LOAD_GAME", CONTROL_LOAD_GAME)
+ .value("CONTROL_OPTIONS_SCREEN", CONTROL_OPTIONS_SCREEN)
+ .value("CONTROL_RETIRE", CONTROL_RETIRE)
+ .value("CONTROL_SAVE_GROUP", CONTROL_SAVE_GROUP)
+ .value("CONTROL_SAVE_NORMAL", CONTROL_SAVE_NORMAL)
+ .value("CONTROL_QUICK_SAVE", CONTROL_QUICK_SAVE)
+ .value("CONTROL_QUICK_LOAD", CONTROL_QUICK_LOAD)
+ .value("CONTROL_ORTHO_CAMERA", CONTROL_ORTHO_CAMERA)
+ .value("CONTROL_CYCLE_CAMERA_FLYING_MODES", CONTROL_CYCLE_CAMERA_FLYING_MODES)
+ .value("CONTROL_ISOMETRIC_CAMERA_LEFT", CONTROL_ISOMETRIC_CAMERA_LEFT)
+ .value("CONTROL_ISOMETRIC_CAMERA_RIGHT", CONTROL_ISOMETRIC_CAMERA_RIGHT)
+ .value("CONTROL_FLYING_CAMERA", CONTROL_FLYING_CAMERA)
+ .value("CONTROL_MOUSE_FLYING_CAMERA", CONTROL_MOUSE_FLYING_CAMERA)
+ .value("CONTROL_TOP_DOWN_CAMERA", CONTROL_TOP_DOWN_CAMERA)
+ .value("CONTROL_CIVILOPEDIA", CONTROL_CIVILOPEDIA)
+ .value("CONTROL_RELIGION_SCREEN", CONTROL_RELIGION_SCREEN)
+ .value("CONTROL_CORPORATION_SCREEN", CONTROL_CORPORATION_SCREEN)
+ .value("CONTROL_CIVICS_SCREEN", CONTROL_CIVICS_SCREEN)
+ .value("CONTROL_FOREIGN_SCREEN", CONTROL_FOREIGN_SCREEN)
+ .value("CONTROL_FINANCIAL_SCREEN", CONTROL_FINANCIAL_SCREEN)
+ .value("CONTROL_MILITARY_SCREEN", CONTROL_MILITARY_SCREEN)
+ .value("CONTROL_TECH_CHOOSER", CONTROL_TECH_CHOOSER)
+ .value("CONTROL_TURN_LOG", CONTROL_TURN_LOG)
+ .value("CONTROL_CHAT_ALL", CONTROL_CHAT_ALL)
+ .value("CONTROL_CHAT_TEAM", CONTROL_CHAT_TEAM)
+ .value("CONTROL_DOMESTIC_SCREEN", CONTROL_DOMESTIC_SCREEN)
+ .value("CONTROL_VICTORY_SCREEN", CONTROL_VICTORY_SCREEN)
+ .value("CONTROL_INFO", CONTROL_INFO)
+ .value("CONTROL_GLOBE_VIEW", CONTROL_GLOBE_VIEW)
+ .value("CONTROL_DETAILS", CONTROL_DETAILS)
+ .value("CONTROL_ADMIN_DETAILS", CONTROL_ADMIN_DETAILS)
+ .value("CONTROL_HALL_OF_FAME", CONTROL_HALL_OF_FAME)
+ .value("CONTROL_WORLD_BUILDER", CONTROL_WORLD_BUILDER)
+ .value("CONTROL_DIPLOMACY", CONTROL_DIPLOMACY)
+ .value("CONTROL_SELECT_HEALTHY", CONTROL_SELECT_HEALTHY)
+ .value("CONTROL_ESPIONAGE_SCREEN", CONTROL_ESPIONAGE_SCREEN)
+ .value("CONTROL_FREE_COLONY", CONTROL_FREE_COLONY)
+
+ .value("NUM_CONTROL_TYPES", NUM_CONTROL_TYPES)
+ ;
+
+ python::enum_("PromotionTypes")
+ .value("NO_PROMOTION", NO_PROMOTION)
+ ;
+
+ python::enum_("TechTypes")
+ .value("NO_TECH", NO_TECH)
+ ;
+
+ python::enum_("SpecialistTypes")
+ .value("NO_SPECIALIST", NO_SPECIALIST)
+ ;
+
+ python::enum_("ReligionTypes")
+ .value("NO_RELIGION", NO_RELIGION)
+ ;
+
+ python::enum_("CorporationTypes")
+ .value("NO_CORPORATION", NO_CORPORATION)
+ ;
+
+ python::enum_("HurryTypes")
+ .value("NO_HURRY", NO_HURRY)
+ ;
+
+ python::enum_("UpkeepTypes")
+ .value("NO_UPKEEP", NO_UPKEEP)
+ ;
+
+ python::enum_("CultureLevelTypes")
+ .value("NO_CULTURELEVEL", NO_CULTURELEVEL)
+ ;
+
+ python::enum_("CivicOptionTypes")
+ .value("NO_CIVICOPTION", NO_CIVICOPTION)
+ ;
+
+ python::enum_("CivicTypes")
+ .value("NO_CIVIC", NO_CIVIC)
+ ;
+
+ python::enum_("WarPlanTypes")
+ .value("NO_WARPLAN", NO_WARPLAN)
+ .value("WARPLAN_ATTACKED_RECENT", WARPLAN_ATTACKED_RECENT)
+ .value("WARPLAN_ATTACKED", WARPLAN_ATTACKED)
+ .value("WARPLAN_PREPARING_LIMITED", WARPLAN_PREPARING_LIMITED)
+ .value("WARPLAN_PREPARING_TOTAL", WARPLAN_PREPARING_TOTAL)
+ .value("WARPLAN_LIMITED", WARPLAN_LIMITED)
+ .value("WARPLAN_TOTAL", WARPLAN_TOTAL)
+ .value("WARPLAN_DOGPILE", WARPLAN_DOGPILE)
+ ;
+
+ python::enum_("AreaAITypes")
+ .value("NO_AREAAI", NO_AREAAI)
+ .value("AREAAI_OFFENSIVE", AREAAI_OFFENSIVE)
+ .value("AREAAI_DEFENSIVE", AREAAI_DEFENSIVE)
+ .value("AREAAI_MASSING", AREAAI_MASSING)
+ .value("AREAAI_ASSAULT", AREAAI_ASSAULT)
+ .value("AREAAI_NEUTRAL", AREAAI_NEUTRAL)
+ ;
+
+ python::enum_("EndTurnButtonStates")
+ .value("END_TURN_GO", END_TURN_GO)
+ .value("END_TURN_OVER_HIGHLIGHT", END_TURN_OVER_HIGHLIGHT)
+ .value("END_TURN_OVER_DARK", END_TURN_OVER_DARK)
+ .value("NUM_END_TURN_STATES", NUM_END_TURN_STATES)
+ ;
+
+ python::enum_("FogOfWarModeTypes")
+ .value("FOGOFWARMODE_OFF", FOGOFWARMODE_OFF)
+ .value("FOGOFWARMODE_UNEXPLORED", FOGOFWARMODE_UNEXPLORED)
+ .value("NUM_FOGOFWARMODE_TYPES", NUM_FOGOFWARMODE_TYPES)
+ ;
+
+ python::enum_("AnimationTypes")
+ .value("NONE_ANIMATION", NONE_ANIMATION)
+ .value("BONUSANIMATION_UNIMPROVED", BONUSANIMATION_UNIMPROVED)
+ .value("BONUSANIMATION_NOT_WORKED", BONUSANIMATION_NOT_WORKED)
+ .value("BONUSANIMATION_WORKED", BONUSANIMATION_WORKED)
+ .value("IMPROVEMENTANIMATION_OFF", IMPROVEMENTANIMATION_OFF)
+ .value("IMPROVEMENTANIMATION_ON", IMPROVEMENTANIMATION_ON)
+ .value("IMPROVEMENTANIMATION_OFF_EXTRA", IMPROVEMENTANIMATION_OFF_EXTRA)
+ .value("IMPROVEMENTANIMATION_ON_EXTRA_1", IMPROVEMENTANIMATION_ON_EXTRA_1)
+ .value("IMPROVEMENTANIMATION_ON_EXTRA_2", IMPROVEMENTANIMATION_ON_EXTRA_2)
+ .value("IMPROVEMENTANIMATION_ON_EXTRA_3", IMPROVEMENTANIMATION_ON_EXTRA_3)
+ .value("IMPROVEMENTANIMATION_ON_EXTRA_4", IMPROVEMENTANIMATION_ON_EXTRA_4)
+ ;
+
+ python::enum_("EntityEventTypes")
+ .value( "ENTITY_EVENT_NONE", ENTITY_EVENT_NONE )
+ ;
+
+ python::enum_("AnimationPathTypes")
+ .value( "ANIMATIONPATH_NONE", ANIMATIONPATH_NONE )
+ .value( "ANIMATIONPATH_IDLE", ANIMATIONPATH_IDLE )
+ .value( "ANIMATIONPATH_MOVE", ANIMATIONPATH_MOVE )
+ .value( "ANIMATIONPATH_RANDOMIZE_ANIMATION_SET", ANIMATIONPATH_RANDOMIZE_ANIMATION_SET )
+ .value( "ANIMATIONPATH_NUKE_STRIKE", ANIMATIONPATH_NUKE_STRIKE )
+ .value( "ANIMATIONPATH_MELEE_STRIKE", ANIMATIONPATH_MELEE_STRIKE )
+ .value( "ANIMATIONPATH_MELEE_HURT", ANIMATIONPATH_MELEE_HURT )
+ .value( "ANIMATIONPATH_MELEE_DIE", ANIMATIONPATH_MELEE_DIE )
+ .value( "ANIMATIONPATH_MELEE_FORTIFIED", ANIMATIONPATH_MELEE_FORTIFIED )
+ .value( "ANIMATIONPATH_MELEE_DIE_FADE", ANIMATIONPATH_MELEE_DIE_FADE )
+ .value( "ANIMATIONPATH_RANGED_STRIKE", ANIMATIONPATH_RANGED_STRIKE )
+ .value( "ANIMATIONPATH_RANGED_DIE", ANIMATIONPATH_RANGED_DIE )
+ .value( "ANIMATIONPATH_RANGED_FORTIFIED", ANIMATIONPATH_RANGED_FORTIFIED )
+ .value( "ANIMATIONPATH_RANGED_RUNHIT", ANIMATIONPATH_RANGED_RUNHIT )
+ .value( "ANIMATIONPATH_RANGED_RUNDIE", ANIMATIONPATH_RANGED_RUNDIE )
+ .value( "ANIMATIONPATH_RANGED_DIE_FADE", ANIMATIONPATH_RANGED_DIE_FADE )
+ .value( "ANIMATIONPATH_LEADER_COMMAND", ANIMATIONPATH_LEADER_COMMAND )
+ .value( "ANIMATIONPATH_AIRFADEIN", ANIMATIONPATH_AIRFADEIN )
+ .value( "ANIMATIONPATH_AIRFADEOUT", ANIMATIONPATH_AIRFADEOUT )
+ .value( "ANIMATIONPATH_AIRSTRIKE", ANIMATIONPATH_AIRSTRIKE )
+ .value( "ANIMATIONPATH_AIRBOMB", ANIMATIONPATH_AIRBOMB )
+ ;
+
+ python::enum_("AnimationCategoryTypes")
+ .value("ANIMCAT_NONE", ANIMCAT_NONE)
+ ;
+
+ python::enum_("CursorTypes")
+ .value("NO_CURSOR", NO_CURSOR)
+ ;
+
+ python::enum_("TradeableItems")
+ .value("NO_TRADEABLE_ITEMS", TRADE_ITEM_NONE)
+ .value("TRADE_GOLD", TRADE_GOLD)
+ .value("TRADE_GOLD_PER_TURN", TRADE_GOLD_PER_TURN)
+ .value("TRADE_MAPS", TRADE_MAPS)
+ .value("TRADE_VASSAL", TRADE_VASSAL)
+ .value("TRADE_SURRENDER", TRADE_SURRENDER)
+ .value("TRADE_OPEN_BORDERS", TRADE_OPEN_BORDERS)
+ .value("TRADE_DEFENSIVE_PACT", TRADE_DEFENSIVE_PACT)
+ .value("TRADE_PERMANENT_ALLIANCE", TRADE_PERMANENT_ALLIANCE)
+ .value("TRADE_PEACE_TREATY", TRADE_PEACE_TREATY)
+ .value("NUM_BASIC_ITEMS", NUM_BASIC_ITEMS)
+ .value("TRADE_TECHNOLOGIES", TRADE_TECHNOLOGIES)
+ .value("TRADE_RESOURCES", TRADE_RESOURCES)
+ .value("TRADE_CITIES", TRADE_CITIES)
+ .value("TRADE_PEACE", TRADE_PEACE)
+ .value("TRADE_WAR", TRADE_WAR)
+ .value("TRADE_EMBARGO", TRADE_EMBARGO)
+ .value("TRADE_CIVIC", TRADE_CIVIC)
+ .value("TRADE_RELIGION", TRADE_RELIGION)
+ .value("NUM_TRADEABLE_HEADINGS", NUM_TRADEABLE_HEADINGS)
+ .value("NUM_TRADEABLE_ITEMS", NUM_TRADEABLE_ITEMS)
+ ;
+
+ python::enum_("DiploEventTypes")
+ .value("NO_DIPLOEVENT", NO_DIPLOEVENT)
+ .value("DIPLOEVENT_CONTACT", DIPLOEVENT_CONTACT)
+ .value("DIPLOEVENT_AI_CONTACT", DIPLOEVENT_AI_CONTACT)
+ .value("DIPLOEVENT_FAILED_CONTACT", DIPLOEVENT_FAILED_CONTACT)
+ .value("DIPLOEVENT_GIVE_HELP", DIPLOEVENT_GIVE_HELP)
+ .value("DIPLOEVENT_REFUSED_HELP", DIPLOEVENT_REFUSED_HELP)
+ .value("DIPLOEVENT_ACCEPT_DEMAND", DIPLOEVENT_ACCEPT_DEMAND)
+ .value("DIPLOEVENT_REJECTED_DEMAND", DIPLOEVENT_REJECTED_DEMAND)
+ .value("DIPLOEVENT_DEMAND_WAR", DIPLOEVENT_DEMAND_WAR)
+ .value("DIPLOEVENT_CONVERT", DIPLOEVENT_CONVERT)
+ .value("DIPLOEVENT_NO_CONVERT", DIPLOEVENT_NO_CONVERT)
+ .value("DIPLOEVENT_REVOLUTION", DIPLOEVENT_REVOLUTION)
+ .value("DIPLOEVENT_NO_REVOLUTION", DIPLOEVENT_NO_REVOLUTION)
+ .value("DIPLOEVENT_JOIN_WAR", DIPLOEVENT_JOIN_WAR)
+ .value("DIPLOEVENT_NO_JOIN_WAR", DIPLOEVENT_NO_JOIN_WAR)
+ .value("DIPLOEVENT_STOP_TRADING", DIPLOEVENT_STOP_TRADING)
+ .value("DIPLOEVENT_NO_STOP_TRADING", DIPLOEVENT_NO_STOP_TRADING)
+ .value("DIPLOEVENT_ASK_HELP", DIPLOEVENT_ASK_HELP)
+ .value("DIPLOEVENT_MADE_DEMAND", DIPLOEVENT_MADE_DEMAND)
+ .value("DIPLOEVENT_RESEARCH_TECH", DIPLOEVENT_RESEARCH_TECH)
+ .value("DIPLOEVENT_TARGET_CITY", DIPLOEVENT_TARGET_CITY)
+ .value("DIPLOEVENT_MADE_DEMAND_VASSAL", DIPLOEVENT_MADE_DEMAND_VASSAL)
+ .value("NUM_DIPLOEVENT_TYPES", NUM_DIPLOEVENT_TYPES)
+ ;
+
+ python::enum_("DiploCommentTypes")
+ .value("NO_DIPLOCOMMENT", NO_DIPLOCOMMENT)
+ ;
+
+ python::enum_("NetContactTypes")
+ .value("NO_NETCONTACT", NO_NETCONTACT)
+ .value("NETCONTACT_INITIAL", NETCONTACT_INITIAL)
+ .value("NETCONTACT_RESPONSE", NETCONTACT_RESPONSE)
+ .value("NETCONTACT_ESTABLISHED", NETCONTACT_ESTABLISHED)
+ .value("NETCONTACT_BUSY", NETCONTACT_BUSY)
+ .value("NUM_NETCONTACT_TYPES", NUM_NETCONTACT_TYPES)
+ ;
+
+ python::enum_("ContactTypes")
+ .value("CONTACT_RELIGION_PRESSURE", CONTACT_RELIGION_PRESSURE)
+ .value("CONTACT_CIVIC_PRESSURE", CONTACT_CIVIC_PRESSURE)
+ .value("CONTACT_JOIN_WAR", CONTACT_JOIN_WAR)
+ .value("CONTACT_STOP_TRADING", CONTACT_STOP_TRADING)
+ .value("CONTACT_GIVE_HELP", CONTACT_GIVE_HELP)
+ .value("CONTACT_ASK_FOR_HELP", CONTACT_ASK_FOR_HELP)
+ .value("CONTACT_DEMAND_TRIBUTE", CONTACT_DEMAND_TRIBUTE)
+ .value("CONTACT_OPEN_BORDERS", CONTACT_OPEN_BORDERS)
+ .value("CONTACT_DEFENSIVE_PACT", CONTACT_DEFENSIVE_PACT)
+ .value("CONTACT_PERMANENT_ALLIANCE", CONTACT_PERMANENT_ALLIANCE)
+ .value("CONTACT_PEACE_TREATY", CONTACT_PEACE_TREATY)
+ .value("CONTACT_TRADE_TECH", CONTACT_TRADE_TECH)
+ .value("CONTACT_TRADE_BONUS", CONTACT_TRADE_BONUS)
+ .value("CONTACT_TRADE_MAP", CONTACT_TRADE_MAP)
+ .value("NUM_CONTACT_TYPES", NUM_CONTACT_TYPES)
+ ;
+
+ python::enum_("MemoryTypes")
+ .value("MEMORY_DECLARED_WAR", MEMORY_DECLARED_WAR)
+ .value("MEMORY_DECLARED_WAR_ON_FRIEND", MEMORY_DECLARED_WAR_ON_FRIEND)
+ .value("MEMORY_HIRED_WAR_ALLY", MEMORY_HIRED_WAR_ALLY)
+ .value("MEMORY_NUKED_US", MEMORY_NUKED_US)
+ .value("MEMORY_NUKED_FRIEND", MEMORY_NUKED_FRIEND)
+ .value("MEMORY_RAZED_CITY", MEMORY_RAZED_CITY)
+ .value("MEMORY_RAZED_HOLY_CITY", MEMORY_RAZED_HOLY_CITY)
+ .value("MEMORY_SPY_CAUGHT", MEMORY_SPY_CAUGHT)
+ .value("MEMORY_GIVE_HELP", MEMORY_GIVE_HELP)
+ .value("MEMORY_REFUSED_HELP", MEMORY_REFUSED_HELP)
+ .value("MEMORY_ACCEPT_DEMAND", MEMORY_ACCEPT_DEMAND)
+ .value("MEMORY_REJECTED_DEMAND", MEMORY_REJECTED_DEMAND)
+ .value("MEMORY_ACCEPTED_RELIGION", MEMORY_ACCEPTED_RELIGION)
+ .value("MEMORY_DENIED_RELIGION", MEMORY_DENIED_RELIGION)
+ .value("MEMORY_ACCEPTED_CIVIC", MEMORY_ACCEPTED_CIVIC)
+ .value("MEMORY_DENIED_CIVIC", MEMORY_DENIED_CIVIC)
+ .value("MEMORY_ACCEPTED_JOIN_WAR", MEMORY_ACCEPTED_JOIN_WAR)
+ .value("MEMORY_DENIED_JOIN_WAR", MEMORY_DENIED_JOIN_WAR)
+ .value("MEMORY_ACCEPTED_STOP_TRADING", MEMORY_ACCEPTED_STOP_TRADING)
+ .value("MEMORY_DENIED_STOP_TRADING", MEMORY_DENIED_STOP_TRADING)
+ .value("MEMORY_STOPPED_TRADING", MEMORY_STOPPED_TRADING)
+ .value("MEMORY_STOPPED_TRADING_RECENT", MEMORY_STOPPED_TRADING_RECENT)
+ .value("MEMORY_HIRED_TRADE_EMBARGO", MEMORY_HIRED_TRADE_EMBARGO)
+ .value("MEMORY_MADE_DEMAND", MEMORY_MADE_DEMAND)
+ .value("MEMORY_MADE_DEMAND_RECENT", MEMORY_MADE_DEMAND_RECENT)
+ .value("MEMORY_CANCELLED_OPEN_BORDERS", MEMORY_CANCELLED_OPEN_BORDERS)
+ .value("MEMORY_TRADED_TECH_TO_US", MEMORY_TRADED_TECH_TO_US)
+ .value("MEMORY_RECEIVED_TECH_FROM_ANY", MEMORY_RECEIVED_TECH_FROM_ANY)
+ .value("MEMORY_VOTED_AGAINST_US", MEMORY_VOTED_AGAINST_US)
+ .value("MEMORY_VOTED_FOR_US", MEMORY_VOTED_FOR_US)
+ .value("MEMORY_EVENT_GOOD_TO_US", MEMORY_EVENT_GOOD_TO_US)
+ .value("MEMORY_EVENT_BAD_TO_US", MEMORY_EVENT_BAD_TO_US)
+ .value("MEMORY_LIBERATED_CITIES", MEMORY_LIBERATED_CITIES)
+ .value("NUM_MEMORY_TYPES", NUM_MEMORY_TYPES)
+ ;
+
+ python::enum_("AttitudeTypes")
+ .value("NO_ATTITUDE", NO_ATTITUDE)
+ .value("ATTITUDE_FURIOUS", ATTITUDE_FURIOUS)
+ .value("ATTITUDE_ANNOYED", ATTITUDE_ANNOYED)
+ .value("ATTITUDE_CAUTIOUS", ATTITUDE_CAUTIOUS)
+ .value("ATTITUDE_PLEASED", ATTITUDE_PLEASED)
+ .value("ATTITUDE_FRIENDLY", ATTITUDE_FRIENDLY)
+ .value("NUM_ATTITUDE_TYPES", NUM_ATTITUDE_TYPES)
+ ;
+
+ python::enum_("LeaderheadAction")
+ .value( "NO_LEADERANIM", NO_LEADERANIM )
+ .value( "LEADERANIM_GREETING", LEADERANIM_GREETING )
+ .value( "LEADERANIM_FRIENDLY", LEADERANIM_FRIENDLY )
+ .value( "LEADERANIM_PLEASED", LEADERANIM_PLEASED )
+ .value( "LEADERANIM_CAUTIOUS", LEADERANIM_CAUTIOUS )
+ .value( "LEADERANIM_ANNOYED", LEADERANIM_ANNOYED )
+ .value( "LEADERANIM_FURIOUS", LEADERANIM_FURIOUS )
+ .value( "LEADERANIM_DISAGREE", LEADERANIM_DISAGREE )
+ .value( "LEADERANIM_AGREE", LEADERANIM_AGREE )
+ .value( "NUM_LEADERANIM_TYPES", NUM_LEADERANIM_TYPES )
+ ;
+
+ python::enum_("DiplomacyPowerTypes")
+ .value("NO_DIPLOMACYPOWER", NO_DIPLOMACYPOWER)
+ .value("DIPLOMACYPOWER_WEAKER", DIPLOMACYPOWER_WEAKER)
+ .value("DIPLOMACYPOWER_EQUAL", DIPLOMACYPOWER_EQUAL)
+ .value("DIPLOMACYPOWER_STRONGER", DIPLOMACYPOWER_STRONGER)
+ .value("NUM_DIPLOMACYPOWER_TYPES", NUM_DIPLOMACYPOWER_TYPES)
+ ;
+
+ python::enum_("FeatTypes")
+ .value("FEAT_UNITCOMBAT_ARCHER", FEAT_UNITCOMBAT_ARCHER)
+ .value("FEAT_UNITCOMBAT_MOUNTED", FEAT_UNITCOMBAT_MOUNTED)
+ .value("FEAT_UNITCOMBAT_MELEE", FEAT_UNITCOMBAT_MELEE)
+ .value("FEAT_UNITCOMBAT_SIEGE", FEAT_UNITCOMBAT_SIEGE)
+ .value("FEAT_UNITCOMBAT_GUN", FEAT_UNITCOMBAT_GUN)
+ .value("FEAT_UNITCOMBAT_ARMOR", FEAT_UNITCOMBAT_ARMOR)
+ .value("FEAT_UNITCOMBAT_HELICOPTER", FEAT_UNITCOMBAT_HELICOPTER)
+ .value("FEAT_UNITCOMBAT_NAVAL", FEAT_UNITCOMBAT_NAVAL)
+ .value("FEAT_UNIT_PRIVATEER", FEAT_UNIT_PRIVATEER)
+ .value("FEAT_UNIT_SPY", FEAT_UNIT_SPY)
+ .value("FEAT_NATIONAL_WONDER", FEAT_NATIONAL_WONDER)
+ .value("FEAT_TRADE_ROUTE", FEAT_TRADE_ROUTE)
+ .value("FEAT_COPPER_CONNECTED", FEAT_COPPER_CONNECTED)
+ .value("FEAT_HORSE_CONNECTED", FEAT_HORSE_CONNECTED)
+ .value("FEAT_IRON_CONNECTED", FEAT_IRON_CONNECTED)
+ .value("FEAT_LUXURY_CONNECTED", FEAT_LUXURY_CONNECTED)
+ .value("FEAT_FOOD_CONNECTED", FEAT_FOOD_CONNECTED)
+ .value("FEAT_POPULATION_HALF_MILLION", FEAT_POPULATION_HALF_MILLION)
+ .value("FEAT_POPULATION_1_MILLION", FEAT_POPULATION_1_MILLION)
+ .value("FEAT_POPULATION_2_MILLION", FEAT_POPULATION_2_MILLION)
+ .value("FEAT_POPULATION_5_MILLION", FEAT_POPULATION_5_MILLION)
+ .value("FEAT_POPULATION_10_MILLION", FEAT_POPULATION_10_MILLION)
+ .value("FEAT_POPULATION_20_MILLION", FEAT_POPULATION_20_MILLION)
+ .value("FEAT_POPULATION_50_MILLION", FEAT_POPULATION_50_MILLION)
+ .value("FEAT_POPULATION_100_MILLION", FEAT_POPULATION_100_MILLION)
+ .value("FEAT_POPULATION_200_MILLION", FEAT_POPULATION_200_MILLION)
+ .value("FEAT_POPULATION_500_MILLION", FEAT_POPULATION_500_MILLION)
+ .value("FEAT_POPULATION_1_BILLION", FEAT_POPULATION_1_BILLION)
+ .value("FEAT_POPULATION_2_BILLION", FEAT_POPULATION_2_BILLION)
+ .value("FEAT_CORPORATION_ENABLED", FEAT_CORPORATION_ENABLED)
+ .value("FEAT_PAD", FEAT_PAD)
+ .value("NUM_FEAT_TYPES", NUM_FEAT_TYPES)
+ ;
+
+ python::enum_("SaveGameTypes")
+ .value("SAVEGAME_NONE", SAVEGAME_NONE)
+ .value("SAVEGAME_AUTO", SAVEGAME_AUTO)
+ .value("SAVEGAME_RECOVERY", SAVEGAME_RECOVERY)
+ .value("SAVEGAME_QUICK", SAVEGAME_QUICK)
+ .value("SAVEGAME_NORMAL", SAVEGAME_NORMAL)
+ .value("SAVEGAME_GROUP", SAVEGAME_GROUP)
+ .value("SAVEGAME_DROP_QUIT", SAVEGAME_DROP_QUIT)
+ .value("SAVEGAME_DROP_CONTINUE", SAVEGAME_DROP_CONTINUE)
+ .value("SAVEGAME_PBEM", SAVEGAME_PBEM)
+ .value("SAVEGAME_REPLAY", SAVEGAME_REPLAY)
+ .value("NUM_SAVEGAME_TYPES", NUM_SAVEGAME_TYPES)
+ ;
+
+ python::enum_("GameType")
+ .value("GAME_NONE", GAME_NONE)
+ .value("GAME_SP_NEW", GAME_SP_NEW)
+ .value("GAME_SP_SCENARIO", GAME_SP_SCENARIO)
+ .value("GAME_SP_LOAD", GAME_SP_LOAD)
+ .value("GAME_MP_NEW", GAME_MP_NEW)
+ .value("GAME_MP_SCENARIO", GAME_MP_SCENARIO)
+ .value("GAME_MP_LOAD", GAME_MP_LOAD)
+ .value("GAME_HOTSEAT_NEW", GAME_HOTSEAT_NEW)
+ .value("GAME_HOTSEAT_SCENARIO", GAME_HOTSEAT_SCENARIO)
+ .value("GAME_HOTSEAT_LOAD", GAME_HOTSEAT_LOAD)
+ .value("GAME_PBEM_NEW", GAME_PBEM_NEW)
+ .value("GAME_PBEM_SCENARIO", GAME_PBEM_SCENARIO)
+ .value("GAME_PBEM_LOAD", GAME_PBEM_LOAD)
+ .value("GAME_REPLAY", GAME_REPLAY)
+ .value("NUM_GAMETYPES", NUM_GAMETYPES)
+ ;
+
+ python::enum_("GameMode")
+ .value("NO_GAMEMODE", NO_GAMEMODE)
+ .value("GAMEMODE_NORMAL", GAMEMODE_NORMAL)
+ .value("GAMEMODE_PITBOSS", GAMEMODE_PITBOSS)
+ .value("NUM_GAMEMODES", NUM_GAMEMODES)
+ ;
+
+ python::enum_("InterfaceVisibility")
+ .value("INTERFACE_SHOW", INTERFACE_SHOW)
+ .value("INTERFACE_HIDE", INTERFACE_HIDE)
+ .value("INTERFACE_HIDE_ALL", INTERFACE_HIDE_ALL)
+ .value("INTERFACE_MINIMAP_ONLY", INTERFACE_MINIMAP_ONLY)
+ .value("INTERFACE_ADVANCED_START", INTERFACE_ADVANCED_START)
+ ;
+
+ python::enum_("GenericButtonSizes")
+ .value("BUTTON_SIZE_46", BUTTON_SIZE_46)
+ .value("BUTTON_SIZE_32", BUTTON_SIZE_32)
+ .value("BUTTON_SIZE_24", BUTTON_SIZE_24)
+ .value("BUTTON_SIZE_16", BUTTON_SIZE_16)
+ .value("BUTTON_SIZE_CUSTOM", BUTTON_SIZE_CUSTOM)
+ ;
+
+ python::enum_("WorldBuilderPopupTypes")
+ .value("WBPOPUP_NONE", WBPOPUP_NONE)
+ .value("WBPOPUP_START", WBPOPUP_START)
+ .value("WBPOPUP_CITY", WBPOPUP_CITY)
+ .value("WBPOPUP_UNIT", WBPOPUP_UNIT)
+ .value("WBPOPUP_PLAYER", WBPOPUP_PLAYER)
+ .value("WBPOPUP_PLOT", WBPOPUP_PLOT)
+ .value("WBPOPUP_TERRAIN", WBPOPUP_TERRAIN)
+ .value("WBPOPUP_FEATURE", WBPOPUP_FEATURE)
+ .value("WBPOPUP_IMPROVEMENT", WBPOPUP_IMPROVEMENT)
+ .value("WBPOPUP_GAME", WBPOPUP_GAME)
+ .value("NUM_WBPOPUP", NUM_WBPOPUP)
+ ;
+
+ python::enum_("EventType")
+ .value("EVT_LBUTTONDOWN", EVT_LBUTTONDOWN)
+ .value("EVT_LBUTTONDBLCLICK", EVT_LBUTTONDBLCLICK)
+ .value("EVT_RBUTTONDOWN", EVT_RBUTTONDOWN)
+ .value("EVT_BACK", EVT_BACK)
+ .value("EVT_FORWARD", EVT_FORWARD)
+ .value("EVT_KEYDOWN", EVT_KEYDOWN)
+ .value("EVT_KEYUP", EVT_KEYUP)
+ ;
+
+ python::enum_("LoadType")
+ .value("LOAD_NORMAL", LOAD_NORMAL)
+ .value("LOAD_INIT", LOAD_INIT)
+ .value("LOAD_SETUP", LOAD_SETUP)
+ .value("LOAD_GAMETYPE", LOAD_GAMETYPE)
+ .value("LOAD_REPLAY", LOAD_REPLAY)
+ ;
+
+ python::enum_("FontTypes")
+ .value("TITLE_FONT", TITLE_FONT)
+ .value("GAME_FONT", GAME_FONT)
+ .value("SMALL_FONT", SMALL_FONT)
+ .value("MENU_FONT", MENU_FONT)
+ .value("MENU_HIGHLIGHT_FONT", MENU_HIGHLIGHT_FONT)
+ ;
+
+ python::enum_("PanelStyles")
+ .value("PANEL_STYLE_STANDARD",PANEL_STYLE_STANDARD)
+ .value("PANEL_STYLE_SOLID",PANEL_STYLE_SOLID)
+ .value("PANEL_STYLE_EMPTY",PANEL_STYLE_EMPTY)
+ .value("PANEL_STYLE_FLAT",PANEL_STYLE_FLAT)
+ .value("PANEL_STYLE_IN",PANEL_STYLE_IN)
+ .value("PANEL_STYLE_OUT",PANEL_STYLE_OUT)
+ .value("PANEL_STYLE_EXTERNAL",PANEL_STYLE_EXTERNAL)
+ .value("PANEL_STYLE_DEFAULT",PANEL_STYLE_DEFAULT)
+
+ .value("PANEL_STYLE_CIVILPEDIA",PANEL_STYLE_CIVILPEDIA)
+ .value("PANEL_STYLE_STONE",PANEL_STYLE_STONE)
+ .value("PANEL_STYLE_BLUELARGE",PANEL_STYLE_BLUELARGE)
+ .value("PANEL_STYLE_UNITSTAT",PANEL_STYLE_UNITSTAT)
+ .value("PANEL_STYLE_BLUE50",PANEL_STYLE_BLUE50)
+
+ .value("PANEL_STYLE_TOPBAR",PANEL_STYLE_TOPBAR)
+ .value("PANEL_STYLE_BOTTOMBAR",PANEL_STYLE_BOTTOMBAR)
+ .value("PANEL_STYLE_TECH",PANEL_STYLE_TECH)
+
+ .value("PANEL_STYLE_GAMEHUD_LEFT",PANEL_STYLE_GAMEHUD_LEFT)
+ .value("PANEL_STYLE_GAMEHUD_RIGHT",PANEL_STYLE_GAMEHUD_RIGHT)
+ .value("PANEL_STYLE_GAMEHUD_CENTER",PANEL_STYLE_GAMEHUD_CENTER)
+ .value("PANEL_STYLE_GAMEHUD_STATS",PANEL_STYLE_GAMEHUD_STATS)
+ .value("PANEL_STYLE_GAME_MAP",PANEL_STYLE_GAME_MAP)
+ .value("PANEL_STYLE_GAME_TOPBAR",PANEL_STYLE_GAME_TOPBAR)
+ .value("PANEL_STYLE_HUD_HELP", PANEL_STYLE_HUD_HELP)
+
+ .value("PANEL_STYLE_CITY_LEFT",PANEL_STYLE_CITY_LEFT)
+ .value("PANEL_STYLE_CITY_RIGHT",PANEL_STYLE_CITY_RIGHT)
+ .value("PANEL_STYLE_CITY_TOP",PANEL_STYLE_CITY_TOP)
+ .value("PANEL_STYLE_CITY_TANSHADE",PANEL_STYLE_CITY_TANSHADE)
+ .value("PANEL_STYLE_CITY_INFO",PANEL_STYLE_CITY_INFO)
+ .value("PANEL_STYLE_CITY_TANTL",PANEL_STYLE_CITY_TANTL)
+ .value("PANEL_STYLE_CITY_TANTR",PANEL_STYLE_CITY_TANTR)
+ .value("PANEL_STYLE_CITY_COLUMNL",PANEL_STYLE_CITY_COLUMNL)
+ .value("PANEL_STYLE_CITY_COLUMNC",PANEL_STYLE_CITY_COLUMNC)
+ .value("PANEL_STYLE_CITY_COLUMNR",PANEL_STYLE_CITY_COLUMNR)
+ .value("PANEL_STYLE_CITY_TITLE",PANEL_STYLE_CITY_TITLE)
+
+ .value("PANEL_STYLE_DAWN",PANEL_STYLE_DAWN)
+ .value("PANEL_STYLE_DAWNTOP",PANEL_STYLE_DAWNTOP)
+ .value("PANEL_STYLE_DAWNBOTTOM",PANEL_STYLE_DAWNBOTTOM)
+
+ .value("PANEL_STYLE_MAIN",PANEL_STYLE_MAIN)
+ .value("PANEL_STYLE_MAIN_BLACK25",PANEL_STYLE_MAIN_BLACK25)
+ .value("PANEL_STYLE_MAIN_BLACK50",PANEL_STYLE_MAIN_BLACK50)
+ .value("PANEL_STYLE_MAIN_WHITE",PANEL_STYLE_MAIN_WHITE)
+ .value("PANEL_STYLE_MAIN_WHITETAB",PANEL_STYLE_MAIN_WHITETAB)
+ .value("PANEL_STYLE_MAIN_TAN",PANEL_STYLE_MAIN_TAN)
+ .value("PANEL_STYLE_MAIN_TAN15",PANEL_STYLE_MAIN_TAN15)
+ .value("PANEL_STYLE_MAIN_TANL",PANEL_STYLE_MAIN_TANL)
+ .value("PANEL_STYLE_MAIN_TANR",PANEL_STYLE_MAIN_TANR)
+ .value("PANEL_STYLE_MAIN_TANT",PANEL_STYLE_MAIN_TANT)
+ .value("PANEL_STYLE_MAIN_TANB",PANEL_STYLE_MAIN_TANB)
+ .value("PANEL_STYLE_MAIN_BOTTOMBAR",PANEL_STYLE_MAIN_BOTTOMBAR)
+ .value("PANEL_STYLE_MAIN_SELECT",PANEL_STYLE_MAIN_SELECT)
+ ;
+
+ python::enum_("ButtonStyles")
+ .value("BUTTON_STYLE_STANDARD", BUTTON_STYLE_STANDARD)
+ .value("BUTTON_STYLE_ETCHED", BUTTON_STYLE_ETCHED)
+ .value("BUTTON_STYLE_FLAT", BUTTON_STYLE_FLAT)
+ .value("BUTTON_STYLE_IMAGE", BUTTON_STYLE_IMAGE)
+ .value("BUTTON_STYLE_LABEL", BUTTON_STYLE_LABEL)
+ .value("BUTTON_STYLE_LINK", BUTTON_STYLE_LINK)
+ .value("BUTTON_STYLE_SQUARE", BUTTON_STYLE_SQUARE)
+ .value("BUTTON_STYLE_TOOL", BUTTON_STYLE_TOOL)
+ .value("BUTTON_STYLE_DEFAULT", BUTTON_STYLE_DEFAULT)
+
+ .value("BUTTON_STYLE_CIRCLE", BUTTON_STYLE_CIRCLE)
+ .value("BUTTON_STYLE_CITY_B01", BUTTON_STYLE_CITY_B01)
+ .value("BUTTON_STYLE_CITY_B02TL", BUTTON_STYLE_CITY_B02TL)
+ .value("BUTTON_STYLE_CITY_B02TR", BUTTON_STYLE_CITY_B02TR)
+ .value("BUTTON_STYLE_CITY_B02BL", BUTTON_STYLE_CITY_B02BL)
+ .value("BUTTON_STYLE_CITY_B02BR", BUTTON_STYLE_CITY_B02BR)
+ .value("BUTTON_STYLE_CITY_B03TL", BUTTON_STYLE_CITY_B03TL)
+ .value("BUTTON_STYLE_CITY_B03TC", BUTTON_STYLE_CITY_B03TC)
+ .value("BUTTON_STYLE_CITY_B03TR", BUTTON_STYLE_CITY_B03TR)
+ .value("BUTTON_STYLE_CITY_B03BL", BUTTON_STYLE_CITY_B03BL)
+ .value("BUTTON_STYLE_CITY_B03BC", BUTTON_STYLE_CITY_B03BC)
+ .value("BUTTON_STYLE_CITY_B03BR", BUTTON_STYLE_CITY_B03BR)
+ .value("BUTTON_STYLE_CITY_FLAT", BUTTON_STYLE_CITY_FLAT)
+ .value("BUTTON_STYLE_CITY_PLUS", BUTTON_STYLE_CITY_PLUS)
+ .value("BUTTON_STYLE_CITY_MINUS", BUTTON_STYLE_CITY_MINUS)
+ .value("BUTTON_STYLE_ARROW_LEFT", BUTTON_STYLE_ARROW_LEFT)
+ .value("BUTTON_STYLE_ARROW_RIGHT", BUTTON_STYLE_ARROW_RIGHT)
+ ;
+
+ python::enum_("TableStyles")
+ .value("TABLE_STYLE_STANDARD", TABLE_STYLE_STANDARD)
+ .value("TABLE_STYLE_EMPTY", TABLE_STYLE_EMPTY)
+ .value("TABLE_STYLE_ALTEMPTY", TABLE_STYLE_ALTEMPTY)
+ .value("TABLE_STYLE_CITY", TABLE_STYLE_CITY)
+ .value("TABLE_STYLE_EMPTYSELECTINACTIVE", TABLE_STYLE_EMPTYSELECTINACTIVE)
+ .value("TABLE_STYLE_ALTDEFAULT", TABLE_STYLE_ALTDEFAULT)
+ .value("TABLE_STYLE_STAGINGROOM", TABLE_STYLE_STAGINGROOM)
+ ;
+
+ python::enum_("EventContextTypes")
+ .value("NO_EVENTCONTEXT", NO_EVENTCONTEXT)
+ .value("EVENTCONTEXT_SELF", EVENTCONTEXT_SELF)
+ .value("EVENTCONTEXT_ALL", EVENTCONTEXT_ALL)
+ ;
+
+ python::enum_("TabGroupTypes")
+ .value("NO_TABGROUP", NO_TABGROUP)
+
+ .value("TABGROUP_GAME", TABGROUP_GAME)
+ .value("TABGROUP_INPUT", TABGROUP_INPUT)
+ .value("TABGROUP_GRAPHICS", TABGROUP_GRAPHICS)
+ .value("TABGROUP_AUDIO", TABGROUP_AUDIO)
+ .value("TABGROUP_CLOCK", TABGROUP_CLOCK)
+
+ .value("NUM_TABGROUPS", NUM_TABGROUPS)
+ ;
+
+ python::enum_("ReplayMessageTypes")
+ .value("NO_REPLAY_MESSAGE", NO_REPLAY_MESSAGE)
+
+ .value("REPLAY_MESSAGE_MAJOR_EVENT", REPLAY_MESSAGE_MAJOR_EVENT)
+ .value("REPLAY_MESSAGE_CITY_FOUNDED", REPLAY_MESSAGE_CITY_FOUNDED)
+ .value("REPLAY_MESSAGE_PLOT_OWNER_CHANGE", REPLAY_MESSAGE_PLOT_OWNER_CHANGE)
+
+ .value("NUM_REPLAY_MESSAGE_TYPES", NUM_REPLAY_MESSAGE_TYPES)
+ ;
+
+ python::enum_("AudioTag")
+ .value("AUDIOTAG_NONE", AUDIOTAG_NONE)
+ .value("AUDIOTAG_SOUNDID", AUDIOTAG_SOUNDID)
+ .value("AUDIOTAG_CONTEXTID", AUDIOTAG_CONTEXTID)
+ .value("AUDIOTAG_SOUNDTYPE", AUDIOTAG_SOUNDTYPE)
+ .value("AUDIOTAG_2DSCRIPT", AUDIOTAG_2DSCRIPT)
+ .value("AUDIOTAG_3DSCRIPT", AUDIOTAG_3DSCRIPT)
+ .value("AUDIOTAG_SOUNDSCAPE", AUDIOTAG_SOUNDSCAPE)
+ .value("AUDIOTAG_POSITION", AUDIOTAG_POSITION)
+ .value("AUDIOTAG_SCRIPTTYPE", AUDIOTAG_SCRIPTTYPE)
+ .value("AUDIOTAG_LOADTYPE", AUDIOTAG_LOADTYPE)
+ .value("AUDIOTAG_COUNT", AUDIOTAG_COUNT)
+ ;
+
+ python::enum_("CivilopediaPageTypes")
+ .value("NO_CIVILOPEDIA_PAGE", NO_CIVILOPEDIA_PAGE)
+
+ .value("CIVILOPEDIA_PAGE_TECH", CIVILOPEDIA_PAGE_TECH)
+ .value("CIVILOPEDIA_PAGE_UNIT", CIVILOPEDIA_PAGE_UNIT)
+ .value("CIVILOPEDIA_PAGE_BUILDING", CIVILOPEDIA_PAGE_BUILDING)
+ .value("CIVILOPEDIA_PAGE_WONDER", CIVILOPEDIA_PAGE_WONDER)
+ .value("CIVILOPEDIA_PAGE_BONUS", CIVILOPEDIA_PAGE_BONUS)
+ .value("CIVILOPEDIA_PAGE_IMPROVEMENT", CIVILOPEDIA_PAGE_IMPROVEMENT)
+ .value("CIVILOPEDIA_PAGE_PROMOTION", CIVILOPEDIA_PAGE_PROMOTION)
+ .value("CIVILOPEDIA_PAGE_UNIT_GROUP", CIVILOPEDIA_PAGE_UNIT_GROUP)
+ .value("CIVILOPEDIA_PAGE_CIV", CIVILOPEDIA_PAGE_CIV)
+ .value("CIVILOPEDIA_PAGE_LEADER", CIVILOPEDIA_PAGE_LEADER)
+ .value("CIVILOPEDIA_PAGE_RELIGION", CIVILOPEDIA_PAGE_RELIGION)
+ .value("CIVILOPEDIA_PAGE_CORPORATION", CIVILOPEDIA_PAGE_CORPORATION)
+ .value("CIVILOPEDIA_PAGE_CIVIC", CIVILOPEDIA_PAGE_CIVIC)
+ .value("CIVILOPEDIA_PAGE_PROJECT", CIVILOPEDIA_PAGE_PROJECT)
+ .value("CIVILOPEDIA_PAGE_CONCEPT", CIVILOPEDIA_PAGE_CONCEPT)
+ .value("CIVILOPEDIA_PAGE_CONCEPT_NEW", CIVILOPEDIA_PAGE_CONCEPT_NEW)
+ .value("CIVILOPEDIA_PAGE_SPECIALIST", CIVILOPEDIA_PAGE_SPECIALIST)
+ .value("CIVILOPEDIA_PAGE_TERRAIN", CIVILOPEDIA_PAGE_TERRAIN)
+ .value("CIVILOPEDIA_PAGE_FEATURE", CIVILOPEDIA_PAGE_FEATURE)
+ .value("CIVILOPEDIA_PAGE_HINTS", CIVILOPEDIA_PAGE_HINTS)
+
+ .value("NUM_CIVILOPEDIA_PAGE_TYPES", NUM_CIVILOPEDIA_PAGE_TYPES)
+ ;
+
+ python::enum_("ActionSubTypes")
+ .value("NO_ACTIONSUBTYPE", NO_ACTIONSUBTYPE)
+
+ .value("ACTIONSUBTYPE_INTERFACEMODE", ACTIONSUBTYPE_INTERFACEMODE)
+ .value("ACTIONSUBTYPE_COMMAND", ACTIONSUBTYPE_COMMAND)
+ .value("ACTIONSUBTYPE_BUILD", ACTIONSUBTYPE_BUILD)
+ .value("ACTIONSUBTYPE_PROMOTION", ACTIONSUBTYPE_PROMOTION)
+ .value("ACTIONSUBTYPE_UNIT", ACTIONSUBTYPE_UNIT)
+ .value("ACTIONSUBTYPE_RELIGION", ACTIONSUBTYPE_RELIGION)
+ .value("ACTIONSUBTYPE_SPECIALIST", ACTIONSUBTYPE_SPECIALIST)
+ .value("ACTIONSUBTYPE_BUILDING", ACTIONSUBTYPE_BUILDING)
+ .value("ACTIONSUBTYPE_CONTROL", ACTIONSUBTYPE_CONTROL)
+ .value("ACTIONSUBTYPE_AUTOMATE", ACTIONSUBTYPE_AUTOMATE)
+ .value("ACTIONSUBTYPE_MISSION", ACTIONSUBTYPE_MISSION)
+
+ .value("NUM_ACTIONSUBTYPES", NUM_ACTIONSUBTYPES)
+ ;
+
+ python::enum_("GameMessageTypes")
+ .value("GAMEMESSAGE_NETWORK_READY", GAMEMESSAGE_NETWORK_READY)
+ .value("GAMEMESSAGE_SAVE_GAME_FLAG", GAMEMESSAGE_SAVE_GAME_FLAG)
+ .value("GAMEMESSAGE_SAVE_FLAG_ACK", GAMEMESSAGE_SAVE_FLAG_ACK)
+ .value("GAMEMESSAGE_VERIFY_VERSION", GAMEMESSAGE_VERIFY_VERSION)
+ .value("GAMEMESSAGE_VERSION_NACK", GAMEMESSAGE_VERSION_NACK)
+ .value("GAMEMESSAGE_VERSION_WARNING", GAMEMESSAGE_VERSION_WARNING)
+ .value("GAMEMESSAGE_GAME_TYPE", GAMEMESSAGE_GAME_TYPE)
+ .value("GAMEMESSAGE_ID_ASSIGNMENT", GAMEMESSAGE_ID_ASSIGNMENT)
+ .value("GAMEMESSAGE_FILE_INFO", GAMEMESSAGE_FILE_INFO)
+ .value("GAMEMESSAGE_PICK_YOUR_CIV", GAMEMESSAGE_PICK_YOUR_CIV)
+ .value("GAMEMESSAGE_CIV_CHOICE", GAMEMESSAGE_CIV_CHOICE)
+ .value("GAMEMESSAGE_CONFIRM_CIV_CLAIM", GAMEMESSAGE_CONFIRM_CIV_CLAIM)
+ .value("GAMEMESSAGE_CLAIM_INFO", GAMEMESSAGE_CLAIM_INFO)
+ .value("GAMEMESSAGE_CIV_CHOICE_ACK", GAMEMESSAGE_CIV_CHOICE_ACK)
+ .value("GAMEMESSAGE_CIV_CHOICE_NACK", GAMEMESSAGE_CIV_CHOICE_NACK)
+ .value("GAMEMESSAGE_CIV_CHOSEN", GAMEMESSAGE_CIV_CHOSEN)
+ .value("GAMEMESSAGE_INTERIM_NOTICE", GAMEMESSAGE_INTERIM_NOTICE)
+ .value("GAMEMESSAGE_INIT_INFO", GAMEMESSAGE_INIT_INFO)
+ .value("GAMEMESSAGE_MAPSCRIPT_CHECK", GAMEMESSAGE_MAPSCRIPT_CHECK)
+ .value("GAMEMESSAGE_MAPSCRIPT_ACK", GAMEMESSAGE_MAPSCRIPT_ACK)
+ .value("GAMEMESSAGE_LOAD_GAME", GAMEMESSAGE_LOAD_GAME)
+ .value("GAMEMESSAGE_PLAYER_ID", GAMEMESSAGE_PLAYER_ID)
+ .value("GAMEMESSAGE_SLOT_REASSIGNMENT", GAMEMESSAGE_SLOT_REASSIGNMENT)
+ .value("GAMEMESSAGE_PLAYER_INFO", GAMEMESSAGE_PLAYER_INFO)
+ .value("GAMEMESSAGE_GAME_INFO", GAMEMESSAGE_GAME_INFO)
+ .value("GAMEMESSAGE_REASSIGN_PLAYER", GAMEMESSAGE_REASSIGN_PLAYER)
+ .value("GAMEMESSAGE_PITBOSS_INFO", GAMEMESSAGE_PITBOSS_INFO)
+ .value("GAMEMESSAGE_LAUNCHING_INFO", GAMEMESSAGE_LAUNCHING_INFO)
+ .value("GAMEMESSAGE_INIT_GAME", GAMEMESSAGE_INIT_GAME)
+ .value("GAMEMESSAGE_INIT_PLAYERS", GAMEMESSAGE_INIT_PLAYERS)
+ .value("GAMEMESSAGE_AUTH_REQUEST", GAMEMESSAGE_AUTH_REQUEST)
+ .value("GAMEMESSAGE_AUTH_RESPONSE", GAMEMESSAGE_AUTH_RESPONSE)
+ .value("GAMEMESSAGE_SYNCH_START", GAMEMESSAGE_SYNCH_START)
+ .value("GAMEMESSAGE_PLAYER_OPTION", GAMEMESSAGE_PLAYER_OPTION)
+ .value("GAMEMESSAGE_EXTENDED_GAME", GAMEMESSAGE_EXTENDED_GAME)
+ .value("GAMEMESSAGE_AUTO_MOVES", GAMEMESSAGE_AUTO_MOVES)
+ .value("GAMEMESSAGE_TURN_COMPLETE", GAMEMESSAGE_TURN_COMPLETE)
+ .value("GAMEMESSAGE_JOIN_GROUP", GAMEMESSAGE_JOIN_GROUP)
+ .value("GAMEMESSAGE_PUSH_MISSION", GAMEMESSAGE_PUSH_MISSION)
+ .value("GAMEMESSAGE_AUTO_MISSION", GAMEMESSAGE_AUTO_MISSION)
+ .value("GAMEMESSAGE_DO_COMMAND", GAMEMESSAGE_DO_COMMAND)
+ .value("GAMEMESSAGE_PUSH_ORDER", GAMEMESSAGE_PUSH_ORDER)
+ .value("GAMEMESSAGE_POP_ORDER", GAMEMESSAGE_POP_ORDER)
+ .value("GAMEMESSAGE_DO_TASK", GAMEMESSAGE_DO_TASK)
+ .value("GAMEMESSAGE_RESEARCH", GAMEMESSAGE_RESEARCH)
+ .value("GAMEMESSAGE_PERCENT_CHANGE", GAMEMESSAGE_PERCENT_CHANGE)
+ .value("GAMEMESSAGE_ESPIONAGE_CHANGE", GAMEMESSAGE_ESPIONAGE_CHANGE)
+ .value("GAMEMESSAGE_CONVERT", GAMEMESSAGE_CONVERT)
+ .value("GAMEMESSAGE_CHAT", GAMEMESSAGE_CHAT)
+ .value("GAMEMESSAGE_PING", GAMEMESSAGE_PING)
+ .value("GAMEMESSAGE_SIGN", GAMEMESSAGE_SIGN)
+ .value("GAMEMESSAGE_LINE_ENTITY", GAMEMESSAGE_LINE_ENTITY)
+ .value("GAMEMESSAGE_SIGN_DELETE", GAMEMESSAGE_SIGN_DELETE)
+ .value("GAMEMESSAGE_LINE_ENTITY_DELETE", GAMEMESSAGE_LINE_ENTITY_DELETE)
+ .value("GAMEMESSAGE_LINE_GROUP_DELETE", GAMEMESSAGE_LINE_GROUP_DELETE)
+ .value("GAMEMESSAGE_PAUSE", GAMEMESSAGE_PAUSE)
+ .value("GAMEMESSAGE_MP_KICK", GAMEMESSAGE_MP_KICK)
+ .value("GAMEMESSAGE_MP_RETIRE", GAMEMESSAGE_MP_RETIRE)
+ .value("GAMEMESSAGE_CLOSE_CONNECTION", GAMEMESSAGE_CLOSE_CONNECTION)
+ .value("GAMEMESSAGE_NEVER_JOINED", GAMEMESSAGE_NEVER_JOINED)
+ .value("GAMEMESSAGE_MP_DROP_INIT", GAMEMESSAGE_MP_DROP_INIT)
+ .value("GAMEMESSAGE_MP_DROP_VOTE", GAMEMESSAGE_MP_DROP_VOTE)
+ .value("GAMEMESSAGE_MP_DROP_UPDATE", GAMEMESSAGE_MP_DROP_UPDATE)
+ .value("GAMEMESSAGE_MP_DROP_RESULT", GAMEMESSAGE_MP_DROP_RESULT)
+ .value("GAMEMESSAGE_MP_DROP_SAVE", GAMEMESSAGE_MP_DROP_SAVE)
+ .value("GAMEMESSAGE_TOGGLE_TRADE", GAMEMESSAGE_TOGGLE_TRADE)
+ .value("GAMEMESSAGE_IMPLEMENT_OFFER", GAMEMESSAGE_IMPLEMENT_OFFER)
+ .value("GAMEMESSAGE_CHANGE_WAR", GAMEMESSAGE_CHANGE_WAR)
+ .value("GAMEMESSAGE_CHANGE_VASSAL", GAMEMESSAGE_CHANGE_VASSAL)
+ .value("GAMEMESSAGE_CHOOSE_ELECTION", GAMEMESSAGE_CHOOSE_ELECTION)
+ .value("GAMEMESSAGE_DIPLO_VOTE", GAMEMESSAGE_DIPLO_VOTE)
+ .value("GAMEMESSAGE_APPLY_EVENT", GAMEMESSAGE_APPLY_EVENT)
+ .value("GAMEMESSAGE_CONTACT_CIV", GAMEMESSAGE_CONTACT_CIV)
+ .value("GAMEMESSAGE_DIPLO_CHAT", GAMEMESSAGE_DIPLO_CHAT)
+ .value("GAMEMESSAGE_SEND_OFFER", GAMEMESSAGE_SEND_OFFER)
+ .value("GAMEMESSAGE_DIPLO_EVENT", GAMEMESSAGE_DIPLO_EVENT)
+ .value("GAMEMESSAGE_RENEGOTIATE", GAMEMESSAGE_RENEGOTIATE)
+ .value("GAMEMESSAGE_RENEGOTIATE_ITEM", GAMEMESSAGE_RENEGOTIATE_ITEM)
+ .value("GAMEMESSAGE_EXIT_TRADE", GAMEMESSAGE_EXIT_TRADE)
+ .value("GAMEMESSAGE_KILL_DEAL", GAMEMESSAGE_KILL_DEAL)
+ .value("GAMEMESSAGE_SAVE_GAME", GAMEMESSAGE_SAVE_GAME)
+ .value("GAMEMESSAGE_UPDATE_CIVICS", GAMEMESSAGE_UPDATE_CIVICS)
+ .value("GAMEMESSAGE_CLEAR_TABLE", GAMEMESSAGE_CLEAR_TABLE)
+ .value("GAMEMESSAGE_POPUP_PROCESSED", GAMEMESSAGE_POPUP_PROCESSED)
+ .value("GAMEMESSAGE_DIPLOMACY_PROCESSED", GAMEMESSAGE_DIPLOMACY_PROCESSED)
+ .value("GAMEMESSAGE_HOT_JOIN_NOTICE", GAMEMESSAGE_HOT_JOIN_NOTICE)
+ .value("GAMEMESSAGE_HOT_DROP_NOTICE", GAMEMESSAGE_HOT_DROP_NOTICE)
+ .value("GAMEMESSAGE_DIPLOMACY", GAMEMESSAGE_DIPLOMACY)
+ .value("GAMEMESSAGE_POPUP", GAMEMESSAGE_POPUP)
+ .value("GAMEMESSAGE_EVENT_TRIGGERED", GAMEMESSAGE_EVENT_TRIGGERED)
+ .value("GAMEMESSAGE_EMPIRE_SPLIT", GAMEMESSAGE_EMPIRE_SPLIT)
+ .value("GAMEMESSAGE_LAUNCH_SPACESHIP", GAMEMESSAGE_LAUNCH_SPACESHIP)
+ .value("GAMEMESSAGE_ADVANCED_START_ACTION", GAMEMESSAGE_ADVANCED_START_ACTION)
+ .value("GAMEMESSAGE_FOUND_RELIGION", GAMEMESSAGE_FOUND_RELIGION)
+ .value("GAMEMESSAGE_MOD_NET_MESSAGE", GAMEMESSAGE_MOD_NET_MESSAGE)
+ ;
+
+ python::enum_