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_("PopupControlLayout") + .value("POPUP_LAYOUT_LEFT", POPUP_LAYOUT_LEFT) + .value("POPUP_LAYOUT_CENTER", POPUP_LAYOUT_CENTER) + .value("POPUP_LAYOUT_RIGHT", POPUP_LAYOUT_RIGHT) + .value("POPUP_LAYOUT_STRETCH", POPUP_LAYOUT_STRETCH) + .value("POPUP_LAYOUT_NUMLAYOUTS", POPUP_LAYOUT_NUMLAYOUTS) + ; + + python::enum_("JustificationTypes") + .value("DLL_FONT_LEFT_JUSTIFY", DLL_FONT_LEFT_JUSTIFY) + .value("DLL_FONT_RIGHT_JUSTIFY", DLL_FONT_RIGHT_JUSTIFY) + .value("DLL_FONT_CENTER_JUSTIFY", DLL_FONT_CENTER_JUSTIFY) + .value("DLL_FONT_CENTER_VERTICALLY", DLL_FONT_CENTER_VERTICALLY) + .value("DLL_FONT_ADDITIVE", DLL_FONT_ADDITIVE) + ; + + python::enum_("ToolTipAlignTypes") + .value("TOOLTIP_TOP_LEFT", TOOLTIP_TOP_LEFT) + .value("TOOLTIP_TOP_INLEFT", TOOLTIP_TOP_INLEFT) + .value("TOOLTIP_TOP_CENTER", TOOLTIP_TOP_CENTER) + .value("TOOLTIP_TOP_INRIGHT", TOOLTIP_TOP_INRIGHT) + .value("TOOLTIP_TOP_RIGHT", TOOLTIP_TOP_RIGHT) + + .value("TOOLTIP_INTOP_RIGHT", TOOLTIP_INTOP_RIGHT) + .value("TOOLTIP_CENTER_RIGHT", TOOLTIP_CENTER_RIGHT) + .value("TOOLTIP_INBOTTOM_RIGHT", TOOLTIP_INBOTTOM_RIGHT) + + .value("TOOLTIP_BOTTOM_RIGHT", TOOLTIP_BOTTOM_RIGHT) + .value("TOOLTIP_BOTTOM_INRIGHT", TOOLTIP_BOTTOM_INRIGHT) + .value("TOOLTIP_BOTTOM_CENTER", TOOLTIP_BOTTOM_CENTER) + .value("TOOLTIP_BOTTOM_INLEFT", TOOLTIP_BOTTOM_INLEFT) + .value("TOOLTIP_BOTTOM_LEFT", TOOLTIP_BOTTOM_LEFT) + + .value("TOOLTIP_INBOTTOM_LEFT", TOOLTIP_INBOTTOM_LEFT) + .value("TOOLTIP_CENTER_LEFT", TOOLTIP_CENTER_LEFT) + .value("TOOLTIP_INTOP_LEFT", TOOLTIP_INTOP_LEFT) + ; + + python::enum_("ActivationTypes") + .value("ACTIVATE_NORMAL", ACTIVATE_NORMAL) + .value("ACTIVATE_CHILDFOCUS", ACTIVATE_CHILDFOCUS) + .value("ACTIVATE_MIMICPARENT", ACTIVATE_MIMICPARENT) + .value("ACTIVATE_MIMICPARENTFOCUS", ACTIVATE_MIMICPARENTFOCUS) + ; + + python::enum_("HitTestTypes") + .value("HITTEST_DEFAULT", HITTEST_DEFAULT) + .value("HITTEST_NOHIT", HITTEST_NOHIT) + .value("HITTEST_SOLID", HITTEST_SOLID) + .value("HITTEST_ON", HITTEST_ON) + .value("HITTEST_CHILDREN", HITTEST_CHILDREN) + ; + + python::enum_("GraphicLevelTypes") + .value("GRAPHICLEVEL_HIGH", GRAPHICLEVEL_HIGH) + .value("GRAPHICLEVEL_MEDIUM", GRAPHICLEVEL_MEDIUM) + .value("GRAPHICLEVEL_LOW", GRAPHICLEVEL_LOW) + .value("GRAPHICLEVEL_CURRENT", GRAPHICLEVEL_CURRENT) + .value("NUM_GRAPHICLEVELS", NUM_GRAPHICLEVELS) + ; + + python::enum_("EventTypes") + .value("NO_EVENT", NO_EVENT) + ; + + python::enum_("EventTriggerTypes") + .value("NO_EVENTTRIGGER", NO_EVENTTRIGGER) + ; + + python::enum_("EspionageMissionTypes") + .value("NO_ESPIONAGEMISSION", NO_ESPIONAGEMISSION) + ; + + python::enum_("AdvancedStartActionTypes") + .value("NO_ADVANCEDSTARTACTION", NO_ADVANCEDSTARTACTION) + + .value("ADVANCEDSTARTACTION_EXIT", ADVANCEDSTARTACTION_EXIT) + .value("ADVANCEDSTARTACTION_UNIT", ADVANCEDSTARTACTION_UNIT) + .value("ADVANCEDSTARTACTION_CITY", ADVANCEDSTARTACTION_CITY) + .value("ADVANCEDSTARTACTION_POP", ADVANCEDSTARTACTION_POP) + .value("ADVANCEDSTARTACTION_CULTURE", ADVANCEDSTARTACTION_CULTURE) + .value("ADVANCEDSTARTACTION_BUILDING", ADVANCEDSTARTACTION_BUILDING) + .value("ADVANCEDSTARTACTION_IMPROVEMENT", ADVANCEDSTARTACTION_IMPROVEMENT) + .value("ADVANCEDSTARTACTION_ROUTE", ADVANCEDSTARTACTION_ROUTE) + .value("ADVANCEDSTARTACTION_TECH", ADVANCEDSTARTACTION_TECH) + .value("ADVANCEDSTARTACTION_VISIBILITY", ADVANCEDSTARTACTION_VISIBILITY) + .value("ADVANCEDSTARTACTION_AUTOMATE", ADVANCEDSTARTACTION_AUTOMATE) + ; +} diff --git a/CvGameCoreDLL/CyInfoInterface1.cpp b/CvGameCoreDLL/CyInfoInterface1.cpp new file mode 100644 index 0000000..238cde8 --- /dev/null +++ b/CvGameCoreDLL/CyInfoInterface1.cpp @@ -0,0 +1,623 @@ +#include "CvGameCoreDLL.h" +#include "CvInfos.h" + +// +// Python interface for info classes (formerly structs) +// These are simple enough to be exposed directly - no wrappers +// + +void CyInfoPythonInterface1() +{ + OutputDebugString("Python Extension Module - CyInfoPythonInterface1\n"); + + python::class_("CvInfoBase") + + .def("isGraphicalOnly", &CvInfoBase::isGraphicalOnly, "bool ()") + + .def("getType", &CvInfoBase::getType, "string ()") + .def("getButton", &CvInfoBase::getButton, "string ()") + + .def("getTextKey", &CvInfoBase::pyGetTextKey, "wstring ()") + .def("getText", &CvInfoBase::pyGetText, "wstring ()") + .def("getDescription", &CvInfoBase::pyGetDescription, "wstring ()") + .def("getDescriptionForm", &CvInfoBase::pyGetDescriptionForm, "wstring ()") + .def("getCivilopedia", &CvInfoBase::pyGetCivilopedia, "wstring ()") + .def("getStrategy", &CvInfoBase::pyGetStrategy, "wstring ()") + .def("getHelp", &CvInfoBase::pyGetHelp, "wstring ()") + .def("isMatchForLink", &CvInfoBase::isMatchForLink, "bool (string)") + + ; + + python::class_("CvScalableInfo") + .def("setScale", &CvScalableInfo::setScale, "void (float fScale)") + .def("getScale", &CvScalableInfo::getScale, "float ()") + ; + + python::class_ >("CvSpecialistInfo") + .def("getGreatPeopleUnitClass", &CvSpecialistInfo::getGreatPeopleUnitClass, "int ()") + .def("getGreatPeopleRateChange", &CvSpecialistInfo::getGreatPeopleRateChange, "int ()") + .def("getMissionType", &CvSpecialistInfo::getMissionType, "int ()") + + .def("isVisible", &CvSpecialistInfo::isVisible, "bool ()") + + .def("getYieldChange", &CvSpecialistInfo::getYieldChange, "int (int i)") + .def("getCommerceChange", &CvSpecialistInfo::getCommerceChange, "int (int i)") + .def("getExperience", &CvSpecialistInfo::getExperience, "int ()") + .def("getFlavorValue", &CvSpecialistInfo::getFlavorValue, "int (int i)") + + .def("getTexture", &CvSpecialistInfo::getTexture, "string ()") + ; + + python::class_ >("CvTechInfo") + .def("getAdvisorType", &CvTechInfo::getAdvisorType, "int ()") + .def("getAIWeight", &CvTechInfo::getAIWeight, "int ()") + .def("getAITradeModifier", &CvTechInfo::getAITradeModifier, "int ()") + .def("getResearchCost", &CvTechInfo::getResearchCost, "int ()") + .def("getEra", &CvTechInfo::getEra, "int ()") + .def("getTradeRoutes", &CvTechInfo::getTradeRoutes, "int ()") + .def("getFeatureProductionModifier", &CvTechInfo::getFeatureProductionModifier, "int ()") + .def("getWorkerSpeedModifier", &CvTechInfo::getWorkerSpeedModifier, "int ()") + .def("getFirstFreeUnitClass", &CvTechInfo::getFirstFreeUnitClass, "int ()") + .def("getHealth", &CvTechInfo::getHealth, "int ()") + .def("getHappiness", &CvTechInfo::getHappiness, "int ()") + .def("getFirstFreeTechs", &CvTechInfo::getFirstFreeTechs, "int ()") + .def("getAssetValue", &CvTechInfo::getAssetValue, "int ()") + .def("getPowerValue", &CvTechInfo::getPowerValue, "int ()") + + .def("getGridX", &CvTechInfo::getGridX, "int ()") + .def("getGridY", &CvTechInfo::getGridY, "int ()") + + .def("isRepeat", &CvTechInfo::isRepeat, "bool ()") + .def("isTrade", &CvTechInfo::isTrade, "bool ()") + .def("isDisable", &CvTechInfo::isDisable, "bool ()") + .def("isGoodyTech", &CvTechInfo::isGoodyTech, "bool ()") + .def("isExtraWaterSeeFrom", &CvTechInfo::isExtraWaterSeeFrom, "bool ()") + .def("isMapCentering", &CvTechInfo::isMapCentering, "bool ()") + .def("isMapVisible", &CvTechInfo::isMapVisible, "bool ()") + .def("isMapTrading", &CvTechInfo::isMapTrading, "bool ()") + .def("isTechTrading", &CvTechInfo::isTechTrading, "bool ()") + .def("isGoldTrading", &CvTechInfo::isGoldTrading, "bool ()") + .def("isOpenBordersTrading", &CvTechInfo::isOpenBordersTrading, "bool ()") + .def("isDefensivePactTrading", &CvTechInfo::isDefensivePactTrading, "bool ()") + .def("isPermanentAllianceTrading", &CvTechInfo::isPermanentAllianceTrading, "bool ()") + .def("isVassalStateTrading", &CvTechInfo::isVassalStateTrading, "bool ()") + .def("isBridgeBuilding", &CvTechInfo::isBridgeBuilding, "bool ()") + .def("isIrrigation", &CvTechInfo::isIrrigation, "bool ()") + .def("isIgnoreIrrigation", &CvTechInfo::isIgnoreIrrigation, "bool ()") + .def("isWaterWork", &CvTechInfo::isWaterWork, "bool ()") + .def("isRiverTrade", &CvTechInfo::isRiverTrade, "bool ()") + + .def("getQuote", &CvTechInfo::getQuote, "wstring ()") + .def("getSound", &CvTechInfo::getSound, "string ()") + .def("getSoundMP", &CvTechInfo::getSoundMP, "string ()") + + .def("getDomainExtraMoves", &CvTechInfo::getDomainExtraMoves, "int (int i)") + .def("getFlavorValue", &CvTechInfo::getFlavorValue, "int (int i)") + .def("getPrereqOrTechs", &CvTechInfo::getPrereqOrTechs, "int (int i)") + .def("getPrereqAndTechs", &CvTechInfo::getPrereqAndTechs, "int (int i)") + + .def("isCommerceFlexible", &CvTechInfo::isCommerceFlexible, "bool (int i)") + .def("isTerrainTrade", &CvTechInfo::isTerrainTrade, "bool (int i)") + ; + + python::class_ >("CvPromotionInfo") + + .def("getPrereqPromotion", &CvPromotionInfo::getPrereqPromotion, "int ()") + .def("getPrereqOrPromotion1", &CvPromotionInfo::getPrereqOrPromotion1, "int ()") + .def("getPrereqOrPromotion2", &CvPromotionInfo::getPrereqOrPromotion2, "int ()") + .def("getActionInfoIndex", &CvPromotionInfo::getActionInfoIndex, "int ()") + + .def("getTechPrereq", &CvPromotionInfo::getTechPrereq, "int ()") + .def("getStateReligionPrereq", &CvPromotionInfo::getStateReligionPrereq, "int ()") + .def("getVisibilityChange", &CvPromotionInfo::getVisibilityChange, "int ()") + .def("getMovesChange", &CvPromotionInfo::getMovesChange, "int ()") + .def("getMoveDiscountChange", &CvPromotionInfo::getMoveDiscountChange, "int ()") + .def("getAirRangeChange", &CvPromotionInfo::getAirRangeChange, "int ()") + .def("getInterceptChange", &CvPromotionInfo::getInterceptChange, "int ()") + .def("getEvasionChange", &CvPromotionInfo::getEvasionChange, "int ()") + .def("getWithdrawalChange", &CvPromotionInfo::getWithdrawalChange, "int ()") + .def("getCargoChange", &CvPromotionInfo::getCargoChange, "int ()") + .def("getCollateralDamageChange", &CvPromotionInfo::getCollateralDamageChange, "int ()") + .def("getBombardRateChange", &CvPromotionInfo::getBombardRateChange, "int ()") + .def("getFirstStrikesChange", &CvPromotionInfo::getFirstStrikesChange, "int ()") + .def("getChanceFirstStrikesChange", &CvPromotionInfo::getChanceFirstStrikesChange, "int ()") + .def("getEnemyHealChange", &CvPromotionInfo::getEnemyHealChange, "int ()") + .def("getNeutralHealChange", &CvPromotionInfo::getNeutralHealChange, "int ()") + .def("getFriendlyHealChange", &CvPromotionInfo::getFriendlyHealChange, "int ()") + .def("getSameTileHealChange", &CvPromotionInfo::getSameTileHealChange, "int ()") + .def("getAdjacentTileHealChange", &CvPromotionInfo::getAdjacentTileHealChange, "int ()") + .def("getCombatPercent", &CvPromotionInfo::getCombatPercent, "int ()") + .def("getCityAttackPercent", &CvPromotionInfo::getCityAttackPercent, "int ()") + .def("getCityDefensePercent", &CvPromotionInfo::getCityDefensePercent, "int ()") + .def("getHillsAttackPercent", &CvPromotionInfo::getHillsAttackPercent, "int ()") + .def("getHillsDefensePercent", &CvPromotionInfo::getHillsDefensePercent, "int ()") + .def("getCommandType", &CvPromotionInfo::getCommandType, "int ()") + .def("getRevoltProtection", &CvPromotionInfo::getRevoltProtection, "int ()") + .def("getCollateralDamageProtection", &CvPromotionInfo::getCollateralDamageProtection, "int ()") + .def("getPillageChange", &CvPromotionInfo::getPillageChange, "int ()") + .def("getUpgradeDiscount", &CvPromotionInfo::getUpgradeDiscount, "int ()") + .def("getExperiencePercent", &CvPromotionInfo::getExperiencePercent, "int ()") + .def("getKamikazePercent", &CvPromotionInfo::getKamikazePercent, "int ()") + + .def("isLeader", &CvPromotionInfo::isLeader, "bool ()") + .def("isBlitz", &CvPromotionInfo::isBlitz, "bool ()") + .def("isAmphib", &CvPromotionInfo::isAmphib, "bool ()") + .def("isRiver", &CvPromotionInfo::isRiver, "bool ()") + .def("isEnemyRoute", &CvPromotionInfo::isEnemyRoute, "bool ()") + .def("isAlwaysHeal", &CvPromotionInfo::isAlwaysHeal, "bool ()") + .def("isHillsDoubleMove", &CvPromotionInfo::isHillsDoubleMove, "bool ()") + .def("isImmuneToFirstStrikes", &CvPromotionInfo::isImmuneToFirstStrikes, "bool ()") + + .def("getSound", &CvPromotionInfo::getSound, "string ()") + + // Arrays + + .def("getTerrainAttackPercent", &CvPromotionInfo::getTerrainAttackPercent, "int (int i)") + .def("getTerrainDefensePercent", &CvPromotionInfo::getTerrainDefensePercent, "int (int i)") + .def("getFeatureAttackPercent", &CvPromotionInfo::getFeatureAttackPercent, "int (int i)") + .def("getFeatureDefensePercent", &CvPromotionInfo::getFeatureDefensePercent, "int (int i)") + .def("getUnitCombatModifierPercent", &CvPromotionInfo::getUnitCombatModifierPercent, "int (int i)") + .def("getDomainModifierPercent", &CvPromotionInfo::getDomainModifierPercent, "int (int i)") + + .def("getTerrainDoubleMove", &CvPromotionInfo::getTerrainDoubleMove, "bool (int i)") + .def("getFeatureDoubleMove", &CvPromotionInfo::getFeatureDoubleMove, "bool (int i)") + .def("getUnitCombat", &CvPromotionInfo::getUnitCombat, "bool (int i)") + ; + + python::class_ >("CvMissionInfo") + .def("getTime", &CvMissionInfo::getTime, "int ()") + + .def("isSound", &CvMissionInfo::isSound, "bool ()") + .def("isTarget", &CvMissionInfo::isTarget, "bool ()") + .def("isBuild", &CvMissionInfo::isBuild, "bool ()") + .def("getVisible", &CvMissionInfo::getVisible, "bool ()") + + .def("getWaypoint", &CvMissionInfo::getWaypoint, "string ()") + ; + + python::class_("CvActionInfo") + .def("getMissionData", &CvActionInfo::getMissionData, "int ()") + .def("getCommandData", &CvActionInfo::getCommandData, "int ()") + .def("getAutomateType", &CvActionInfo::getAutomateType, "int ()") + + .def("getInterfaceModeType", &CvActionInfo::getInterfaceModeType, "int ()") + .def("getMissionType", &CvActionInfo::getMissionType, "int ()") + .def("getCommandType", &CvActionInfo::getCommandType, "int ()") + .def("getControlType", &CvActionInfo::getControlType, "int ()") + + .def("isConfirmCommand", &CvActionInfo::isConfirmCommand, "bool ()") + .def("isVisible", &CvActionInfo::isVisible, "bool ()") + + .def("getHotKey", &CvActionInfo::getHotKey, "string ()") + .def("getButton", &CvActionInfo::getButton, "string ()") + ; + + python::class_ >("CvUnitInfo") + + .def("getAIWeight", &CvUnitInfo::getAIWeight, "int ()") + .def("getProductionCost", &CvUnitInfo::getProductionCost, "int ()") + .def("getHurryCostModifier", &CvUnitInfo::getHurryCostModifier, "int ()") + .def("getMinAreaSize", &CvUnitInfo::getMinAreaSize, "int ()") + .def("getMoves", &CvUnitInfo::getMoves, "int ()") + .def("getAirRange", &CvUnitInfo::getAirRange, "int ()") + .def("getAirUnitCap", &CvUnitInfo::getAirUnitCap, "int ()") + .def("getDropRange", &CvUnitInfo::getDropRange, "int ()") + .def("getNukeRange", &CvUnitInfo::getNukeRange, "int ()") + .def("getWorkRate", &CvUnitInfo::getWorkRate, "int ()") + .def("getBaseDiscover", &CvUnitInfo::getBaseDiscover, "int ()") + .def("getDiscoverMultiplier", &CvUnitInfo::getDiscoverMultiplier, "int ()") + .def("getBaseHurry", &CvUnitInfo::getBaseHurry, "int ()") + .def("getHurryMultiplier", &CvUnitInfo::getHurryMultiplier, "int ()") + .def("getBaseTrade", &CvUnitInfo::getBaseTrade, "int ()") + .def("getTradeMultiplier", &CvUnitInfo::getTradeMultiplier, "int ()") + .def("getGreatWorkCulture", &CvUnitInfo::getGreatWorkCulture, "int ()") + .def("getEspionagePoints", &CvUnitInfo::getEspionagePoints, "int ()") + .def("getCombat", &CvUnitInfo::getCombat, "int ()") + .def("setCombat", &CvUnitInfo::setCombat, "void (int)") + .def("getCombatLimit", &CvUnitInfo::getCombatLimit, "int ()") + .def("getAirCombat", &CvUnitInfo::getAirCombat, "int ()") + .def("getAirCombatLimit", &CvUnitInfo::getAirCombatLimit, "int ()") + .def("getXPValueAttack", &CvUnitInfo::getXPValueAttack, "int ()") + .def("getXPValueDefense", &CvUnitInfo::getXPValueDefense, "int ()") + .def("getFirstStrikes", &CvUnitInfo::getFirstStrikes, "int ()") + .def("getChanceFirstStrikes", &CvUnitInfo::getChanceFirstStrikes, "int ()") + .def("getInterceptionProbability", &CvUnitInfo::getInterceptionProbability, "int ()") + .def("getEvasionProbability", &CvUnitInfo::getEvasionProbability, "int ()") + .def("getWithdrawalProbability", &CvUnitInfo::getWithdrawalProbability, "int ()") + .def("getCollateralDamage", &CvUnitInfo::getCollateralDamage, "int ()") + .def("getCollateralDamageLimit", &CvUnitInfo::getCollateralDamageLimit, "int ()") + .def("getCollateralDamageMaxUnits", &CvUnitInfo::getCollateralDamageMaxUnits, "int ()") + .def("getCityAttackModifier", &CvUnitInfo::getCityAttackModifier, "int ()") + .def("getCityDefenseModifier", &CvUnitInfo::getCityDefenseModifier, "int ()") + .def("getAnimalCombatModifier", &CvUnitInfo::getAnimalCombatModifier, "int ()") + .def("getHillsAttackModifier", &CvUnitInfo::getHillsAttackModifier, "int ()") + .def("getHillsDefenseModifier", &CvUnitInfo::getHillsDefenseModifier, "int ()") + .def("getBombRate", &CvUnitInfo::getBombRate, "int ()") + .def("getBombardRate", &CvUnitInfo::getBombardRate, "int ()") + .def("getSpecialCargo", &CvUnitInfo::getSpecialCargo, "int ()") + .def("getDomainCargo", &CvUnitInfo::getDomainCargo, "int ()") + + .def("getCargoSpace", &CvUnitInfo::getCargoSpace, "int ()") + .def("getConscriptionValue", &CvUnitInfo::getConscriptionValue, "int ()") + .def("getCultureGarrisonValue", &CvUnitInfo::getCultureGarrisonValue, "int ()") + .def("getExtraCost", &CvUnitInfo::getExtraCost, "int ()") + .def("getAssetValue", &CvUnitInfo::getAssetValue, "int ()") + .def("getPowerValue", &CvUnitInfo::getPowerValue, "int ()") + .def("getUnitClassType", &CvUnitInfo::getUnitClassType, "int ()") + .def("getSpecialUnitType", &CvUnitInfo::getSpecialUnitType, "int ()") + .def("getUnitCaptureClassType", &CvUnitInfo::getUnitCaptureClassType, "int ()") + .def("getUnitCombatType", &CvUnitInfo::getUnitCombatType, "int ()") + .def("getDomainType", &CvUnitInfo::getDomainType, "int ()") + .def("getDefaultUnitAIType", &CvUnitInfo::getDefaultUnitAIType, "int ()") + .def("getInvisibleType", &CvUnitInfo::getInvisibleType, "int ()") + .def("getNumSeeInvisibleTypes", &CvUnitInfo::getNumSeeInvisibleTypes, "int ()") + .def("getSeeInvisibleType", &CvUnitInfo::getSeeInvisibleType, "int (int)") + .def("getAdvisorType", &CvUnitInfo::getAdvisorType, "int ()") + .def("getHolyCity", &CvUnitInfo::getHolyCity, "int ()") + .def("getReligionType", &CvUnitInfo::getReligionType, "int ()") + .def("getStateReligion", &CvUnitInfo::getStateReligion, "int ()") + .def("getPrereqReligion", &CvUnitInfo::getPrereqReligion, "int ()") + .def("getPrereqCorporation", &CvUnitInfo::getPrereqCorporation, "int ()") + .def("getPrereqBuilding", &CvUnitInfo::getPrereqBuilding, "int ()") + .def("getPrereqAndTech", &CvUnitInfo::getPrereqAndTech, "int ()") + .def("getPrereqAndBonus", &CvUnitInfo::getPrereqAndBonus, "int ()") + .def("getGroupSize", &CvUnitInfo::getGroupSize, "int ()") + .def("getGroupDefinitions", &CvUnitInfo::getGroupDefinitions, "int ()") + .def("getMeleeWaveSize", &CvUnitInfo::getMeleeWaveSize, "int ()") + .def("getRangedWaveSize", &CvUnitInfo::getRangedWaveSize, "int ()") + .def("getNumUnitNames", &CvUnitInfo::getNumUnitNames, "int ()") + .def("getCommandType", &CvUnitInfo::getCommandType, "int ()") + + .def("isAnimal", &CvUnitInfo::isAnimal, "bool ()") + .def("isFoodProduction", &CvUnitInfo::isFoodProduction, "bool ()") + .def("isNoBadGoodies", &CvUnitInfo::isNoBadGoodies, "bool ()") + .def("isNoCapture", &CvUnitInfo::isNoCapture, "bool ()") + .def("isRivalTerritory", &CvUnitInfo::isRivalTerritory, "bool ()") + .def("isMilitaryHappiness", &CvUnitInfo::isMilitaryHappiness, "bool ()") + .def("isMilitarySupport", &CvUnitInfo::isMilitarySupport, "bool ()") + .def("isMilitaryProduction", &CvUnitInfo::isMilitaryProduction, "bool ()") + .def("isPillage", &CvUnitInfo::isPillage, "bool ()") + .def("isSpy", &CvUnitInfo::isSpy, "bool ()") + .def("isSabotage", &CvUnitInfo::isSabotage, "bool ()") + .def("isDestroy", &CvUnitInfo::isDestroy, "bool ()") + .def("isStealPlans", &CvUnitInfo::isStealPlans, "bool ()") + .def("isInvestigate", &CvUnitInfo::isInvestigate, "bool ()") + .def("isCounterSpy", &CvUnitInfo::isCounterSpy, "bool ()") + .def("isFound", &CvUnitInfo::isFound, "bool ()") + .def("isGoldenAge", &CvUnitInfo::isGoldenAge, "bool ()") + .def("isInvisible", &CvUnitInfo::isInvisible, "bool ()") + .def("setInvisible", &CvUnitInfo::setInvisible, "void (bool bEnable)") + .def("isFirstStrikeImmune", &CvUnitInfo::isFirstStrikeImmune, "bool ()") + .def("isNoDefensiveBonus", &CvUnitInfo::isNoDefensiveBonus, "bool ()") + .def("isIgnoreBuildingDefense", &CvUnitInfo::isIgnoreBuildingDefense, "bool ()") + .def("isCanMoveImpassable", &CvUnitInfo::isCanMoveImpassable, "bool ()") + .def("isCanMoveAllTerrain", &CvUnitInfo::isCanMoveAllTerrain, "bool ()") + .def("isFlatMovementCost", &CvUnitInfo::isFlatMovementCost, "bool ()") + .def("isIgnoreTerrainCost", &CvUnitInfo::isIgnoreTerrainCost, "bool ()") + .def("isNukeImmune", &CvUnitInfo::isNukeImmune, "bool ()") + .def("isPrereqBonuses", &CvUnitInfo::isPrereqBonuses, "bool ()") + .def("isPrereqReligion", &CvUnitInfo::isPrereqReligion, "bool ()") + .def("isMechUnit", &CvUnitInfo::isMechUnit, "bool ()") + .def("isRenderBelowWater", &CvUnitInfo::isRenderBelowWater, "bool ()") + .def("isSuicide", &CvUnitInfo::isSuicide, "bool ()") + .def("isLineOfSight", &CvUnitInfo::isLineOfSight, "bool ()") + .def("isHiddenNationality", &CvUnitInfo::isHiddenNationality, "bool ()") + .def("isAlwaysHostile", &CvUnitInfo::isAlwaysHostile, "bool ()") + + .def("getUnitMaxSpeed", &CvUnitInfo::getUnitMaxSpeed, "float ()") + .def("getUnitPadTime", &CvUnitInfo::getUnitPadTime, "float ()") + + // Arrays + + .def("getPrereqAndTechs", &CvUnitInfo::getPrereqAndTechs, "int (int i)") + .def("getPrereqOrBonuses", &CvUnitInfo::getPrereqOrBonuses, "int (int i)") + .def("getProductionTraits", &CvUnitInfo::getProductionTraits, "int (int i)") + .def("getFlavorValue", &CvUnitInfo::getFlavorValue, "int (int i)") + .def("getTerrainAttackModifier", &CvUnitInfo::getTerrainAttackModifier, "int (int i)") + .def("getTerrainDefenseModifier", &CvUnitInfo::getTerrainDefenseModifier, "int (int i)") + .def("getFeatureAttackModifier", &CvUnitInfo::getFeatureAttackModifier, "int (int i)") + .def("getFeatureDefenseModifier", &CvUnitInfo::getFeatureDefenseModifier, "int (int i)") + .def("getUnitClassAttackModifier", &CvUnitInfo::getUnitClassAttackModifier, "int (int i)") + .def("getUnitClassDefenseModifier", &CvUnitInfo::getUnitClassDefenseModifier, "int (int i)") + .def("getUnitCombatModifier", &CvUnitInfo::getUnitCombatModifier, "int (int i)") + .def("getDomainModifier", &CvUnitInfo::getDomainModifier, "int (int i)") + .def("getBonusProductionModifier", &CvUnitInfo::getBonusProductionModifier, "int (int i)") + .def("getUnitGroupRequired", &CvUnitInfo::getUnitGroupRequired, "int (int i)") + + .def("getUpgradeUnitClass", &CvUnitInfo::getUpgradeUnitClass, "bool (int i)") + .def("getTargetUnitClass", &CvUnitInfo::getTargetUnitClass, "bool (int i)") + .def("getTargetUnitCombat", &CvUnitInfo::getTargetUnitCombat, "bool (int i)") + .def("getDefenderUnitClass", &CvUnitInfo::getDefenderUnitClass, "bool (int i)") + .def("getDefenderUnitCombat", &CvUnitInfo::getDefenderUnitCombat, "bool (int i)") + .def("getUnitAIType", &CvUnitInfo::getUnitAIType, "bool (int i)") + .def("getNotUnitAIType", &CvUnitInfo::getNotUnitAIType, "bool (int i)") + .def("getBuilds", &CvUnitInfo::getBuilds, "bool (int i)") + .def("getReligionSpreads", &CvUnitInfo::getReligionSpreads, "int (int i)") + .def("getCorporationSpreads", &CvUnitInfo::getCorporationSpreads, "int (int i)") + .def("getTerrainPassableTech", &CvUnitInfo::getTerrainPassableTech, "int (int i)") + .def("getFeaturePassableTech", &CvUnitInfo::getFeaturePassableTech, "int (int i)") + .def("getFlankingStrikeUnitClass", &CvUnitInfo::getFlankingStrikeUnitClass, "int (int i)") + .def("getGreatPeoples", &CvUnitInfo::getGreatPeoples, "bool (int i)") + .def("getBuildings", &CvUnitInfo::getBuildings, "bool (int i)") + .def("getForceBuildings", &CvUnitInfo::getForceBuildings, "bool (int i)") + .def("getTerrainImpassable", &CvUnitInfo::getTerrainImpassable, "bool (int i)") + .def("getFeatureImpassable", &CvUnitInfo::getFeatureImpassable, "bool (int i)") + .def("getTerrainNative", &CvUnitInfo::getTerrainNative, "bool (int i)") + .def("getFeatureNative", &CvUnitInfo::getFeatureNative, "bool (int i)") + .def("getFreePromotions", &CvUnitInfo::getFreePromotions, "bool (int i)") + .def("getLeaderPromotion", &CvUnitInfo::getLeaderPromotion, "int ()") + .def("getLeaderExperience", &CvUnitInfo::getLeaderExperience, "int ()") + + .def("getEarlyArtDefineTag", &CvUnitInfo::getEarlyArtDefineTag, "string (int i, UnitArtStyleTypes eStyle)") + .def("getLateArtDefineTag", &CvUnitInfo::getLateArtDefineTag, "string (int i, UnitArtStyleTypes eStyle)") + .def("getMiddleArtDefineTag", &CvUnitInfo::getMiddleArtDefineTag, "string (int i, UnitArtStyleTypes eStyle)") + .def("getUnitNames", &CvUnitInfo::getUnitNames, "string (int i)") + .def("getArtInfo", &CvUnitInfo::getArtInfo, python::return_value_policy(), "CvArtInfoUnit* (int i, bool bLate)") + ; + + python::class_ >("CvSpecialUnitInfo") + .def("isValid", &CvSpecialUnitInfo::isValid, "bool ()") + .def("isCityLoad", &CvSpecialUnitInfo::isCityLoad, "bool ()") + + .def("isCarrierUnitAIType", &CvSpecialUnitInfo::isCarrierUnitAIType, "bool (int i)") + .def("getProductionTraits", &CvSpecialUnitInfo::getProductionTraits, "int (int i)") + ; + + python::class_ >("CvCivicOptionInfo") + .def("getTraitNoUpkeep", &CvCivicOptionInfo::getTraitNoUpkeep, "bool (int i)") + ; + + python::class_ >("CvCivicInfo") + + .def("getCivicOptionType", &CvCivicInfo::getCivicOptionType, "int ()") + .def("getAnarchyLength", &CvCivicInfo::getAnarchyLength, "int ()") + .def("getUpkeep", &CvCivicInfo::getUpkeep, "int ()") + .def("getAIWeight", &CvCivicInfo::getAIWeight, "int ()") + .def("getGreatPeopleRateModifier", &CvCivicInfo::getGreatPeopleRateModifier, "int ()") + .def("getGreatGeneralRateModifier", &CvCivicInfo::getGreatGeneralRateModifier, "int ()") + .def("getDomesticGreatGeneralRateModifier", &CvCivicInfo::getDomesticGreatGeneralRateModifier, "int ()") + .def("getStateReligionGreatPeopleRateModifier", &CvCivicInfo::getStateReligionGreatPeopleRateModifier, "int ()") + .def("getDistanceMaintenanceModifier", &CvCivicInfo::getDistanceMaintenanceModifier, "int ()") + .def("getNumCitiesMaintenanceModifier", &CvCivicInfo::getNumCitiesMaintenanceModifier, "int ()") + .def("getCorporationMaintenanceModifier", &CvCivicInfo::getCorporationMaintenanceModifier, "int ()") + .def("getExtraHealth", &CvCivicInfo::getExtraHealth, "int ()") + .def("getFreeExperience", &CvCivicInfo::getFreeExperience, "int ()") + .def("getWorkerSpeedModifier", &CvCivicInfo::getWorkerSpeedModifier, "int ()") + .def("getImprovementUpgradeRateModifier", &CvCivicInfo::getImprovementUpgradeRateModifier, "int ()") + .def("getMilitaryProductionModifier", &CvCivicInfo::getMilitaryProductionModifier, "int ()") + .def("getBaseFreeUnits", &CvCivicInfo::getBaseFreeUnits, "int ()") + .def("getBaseFreeMilitaryUnits", &CvCivicInfo::getBaseFreeMilitaryUnits, "int ()") + .def("getFreeUnitsPopulationPercent", &CvCivicInfo::getFreeUnitsPopulationPercent, "int ()") + .def("getFreeMilitaryUnitsPopulationPercent", &CvCivicInfo::getFreeMilitaryUnitsPopulationPercent, "int ()") + .def("getGoldPerUnit", &CvCivicInfo::getGoldPerUnit, "int ()") + .def("getGoldPerMilitaryUnit", &CvCivicInfo::getGoldPerMilitaryUnit, "int ()") + .def("getHappyPerMilitaryUnit", &CvCivicInfo::getHappyPerMilitaryUnit, "int ()") + .def("getLargestCityHappiness", &CvCivicInfo::getLargestCityHappiness, "int ()") + .def("getWarWearinessModifier", &CvCivicInfo::getWarWearinessModifier, "int ()") + .def("getFreeSpecialist", &CvCivicInfo::getFreeSpecialist, "int ()") + .def("getTradeRoutes", &CvCivicInfo::getTradeRoutes, "int ()") + .def("getTechPrereq", &CvCivicInfo::getTechPrereq, "int ()") + .def("getCivicPercentAnger", &CvCivicInfo::getCivicPercentAnger, "int ()") + .def("getMaxConscript", &CvCivicInfo::getMaxConscript, "int ()") + .def("getStateReligionHappiness", &CvCivicInfo::getStateReligionHappiness, "int ()") + .def("getNonStateReligionHappiness", &CvCivicInfo::getNonStateReligionHappiness, "int ()") + .def("getStateReligionUnitProductionModifier", &CvCivicInfo::getStateReligionUnitProductionModifier, "int ()") + .def("getStateReligionBuildingProductionModifier", &CvCivicInfo::getStateReligionBuildingProductionModifier, "int ()") + .def("getStateReligionFreeExperience", &CvCivicInfo::getStateReligionFreeExperience, "int ()") + .def("getExpInBorderModifier", &CvCivicInfo::getExpInBorderModifier, "bool ()") + + .def("isMilitaryFoodProduction", &CvCivicInfo::isMilitaryFoodProduction, "bool ()") + .def("isNoUnhealthyPopulation", &CvCivicInfo::isNoUnhealthyPopulation, "bool ()") + .def("isBuildingOnlyHealthy", &CvCivicInfo::isBuildingOnlyHealthy, "bool ()") + .def("isNoForeignTrade", &CvCivicInfo::isNoForeignTrade, "bool ()") + .def("isNoCorporations", &CvCivicInfo::isNoCorporations, "bool ()") + .def("isNoForeignCorporations", &CvCivicInfo::isNoForeignCorporations, "bool ()") + .def("isStateReligion", &CvCivicInfo::isStateReligion, "bool ()") + .def("isNoNonStateReligionSpread", &CvCivicInfo::isNoNonStateReligionSpread, "bool ()") + + .def("pyGetWeLoveTheKing", &CvCivicInfo::pyGetWeLoveTheKing, "wstring ()") + + // Arrays + + .def("getYieldModifier", &CvCivicInfo::getYieldModifier, "int (int i)") + .def("getCapitalYieldModifier", &CvCivicInfo::getCapitalYieldModifier, "int (int i)") + .def("getTradeYieldModifier", &CvCivicInfo::getTradeYieldModifier, "int (int i)") + .def("getCommerceModifier", &CvCivicInfo::getCommerceModifier, "int (int i)") + .def("getCapitalCommerceModifier", &CvCivicInfo::getCapitalCommerceModifier, "int (int i)") + .def("getSpecialistExtraCommerce", &CvCivicInfo::getSpecialistExtraCommerce, "int (int i)") + .def("getBuildingHappinessChanges", &CvCivicInfo::getBuildingHappinessChanges, "int (int i)") + + //Plako for RtR mod 22.7.2015 + + .def("getRtRExtraSpecialistCounts", &CvCivicInfo::getRtRExtraSpecialistCounts, "int (int i)") + .def("getBuildingHealthChanges", &CvCivicInfo::getBuildingHealthChanges, "int (int i)") + .def("getFeatureHappinessChanges", &CvCivicInfo::getFeatureHappinessChanges, "int (int i)") + + .def("isHurry", &CvCivicInfo::isHurry, "bool (int i)") + .def("isSpecialBuildingNotRequired", &CvCivicInfo::isSpecialBuildingNotRequired, "bool (int i)") + .def("isSpecialistValid", &CvCivicInfo::isSpecialistValid, "bool (int i)") + + .def("getImprovementYieldChanges", &CvCivicInfo::getImprovementYieldChanges, "int (int i, int j)") + ; + + python::class_ >("CvUnitClassInfo") + .def("getMaxGlobalInstances", &CvUnitClassInfo::getMaxGlobalInstances, "int ()") + .def("getMaxTeamInstances", &CvUnitClassInfo::getMaxTeamInstances, "int ()") + .def("getMaxPlayerInstances", &CvUnitClassInfo::getMaxPlayerInstances, "int ()") + .def("getInstanceCostModifier", &CvUnitClassInfo::getInstanceCostModifier, "int ()") + .def("getDefaultUnitIndex", &CvUnitClassInfo::getDefaultUnitIndex, "int ()") + ; + + python::class_ >("CvBuildingInfo") + + .def("getBuildingClassType", &CvBuildingInfo::getBuildingClassType, "int ()") + .def("getVictoryPrereq", &CvBuildingInfo::getVictoryPrereq, "int ()") + .def("getFreeStartEra", &CvBuildingInfo::getFreeStartEra, "int ()") + .def("getMaxStartEra", &CvBuildingInfo::getMaxStartEra, "int ()") + .def("getObsoleteTech", &CvBuildingInfo::getObsoleteTech, "int ()") + .def("getPrereqAndTech", &CvBuildingInfo::getPrereqAndTech, "int ()") + .def("getNoBonus", &CvBuildingInfo::getNoBonus, "int ()") + .def("getPowerBonus", &CvBuildingInfo::getPowerBonus, "int ()") + .def("getFreeBonus", &CvBuildingInfo::getFreeBonus, "int ()") + .def("getNumFreeBonuses", &CvBuildingInfo::getNumFreeBonuses, "int ()") + .def("getFreeBuildingClass", &CvBuildingInfo::getFreeBuildingClass, "int ()") + .def("getFreePromotion", &CvBuildingInfo::getFreePromotion, "int ()") + .def("getCivic", &CvBuildingInfo::getCivicOption, "int ()") + .def("getAIWeight", &CvBuildingInfo::getAIWeight, "int ()") + .def("getProductionCost", &CvBuildingInfo::getProductionCost, "int ()") + .def("getHurryCostModifier", &CvBuildingInfo::getHurryCostModifier, "int ()") + .def("getHurryAngerModifier", &CvBuildingInfo::getHurryAngerModifier, "int ()") + .def("getMinAreaSize", &CvBuildingInfo::getMinAreaSize, "int ()") + .def("getNumCitiesPrereq", &CvBuildingInfo::getNumCitiesPrereq, "int ()") + .def("getNumTeamsPrereq", &CvBuildingInfo::getNumTeamsPrereq, "int ()") + .def("getUnitLevelPrereq", &CvBuildingInfo::getUnitLevelPrereq, "int ()") + .def("getMinLatitude", &CvBuildingInfo::getMinLatitude, "int ()") + .def("getMaxLatitude", &CvBuildingInfo::getMaxLatitude, "int ()") + .def("getGreatPeopleRateModifier", &CvBuildingInfo::getGreatPeopleRateModifier, "int ()") + .def("getGreatGeneralRateModifier", &CvBuildingInfo::getGreatGeneralRateModifier, "int ()") + .def("getDomesticGreatGeneralRateModifier", &CvBuildingInfo::getDomesticGreatGeneralRateModifier, "int ()") + .def("getGlobalGreatPeopleRateModifier", &CvBuildingInfo::getGlobalGreatPeopleRateModifier, "int ()") + .def("getAnarchyModifier", &CvBuildingInfo::getAnarchyModifier, "int ()") + .def("getGoldenAgeModifier", &CvBuildingInfo::getGoldenAgeModifier, "int ()") + .def("getGlobalHurryModifier", &CvBuildingInfo::getGlobalHurryModifier, "int ()") + .def("getFreeExperience", &CvBuildingInfo::getFreeExperience, "int ()") + .def("getGlobalFreeExperience", &CvBuildingInfo::getGlobalFreeExperience, "int ()") + .def("getFoodKept", &CvBuildingInfo::getFoodKept, "int ()") + .def("getAirlift", &CvBuildingInfo::getAirlift, "int ()") + .def("getAirModifier", &CvBuildingInfo::getAirModifier, "int ()") + .def("getAirUnitCapacity", &CvBuildingInfo::getAirUnitCapacity, "int ()") + .def("getNukeModifier", &CvBuildingInfo::getNukeModifier, "int ()") + .def("getNukeExplosionRand", &CvBuildingInfo::getNukeExplosionRand, "int ()") + .def("getFreeSpecialist", &CvBuildingInfo::getFreeSpecialist, "int ()") + .def("getAreaFreeSpecialist", &CvBuildingInfo::getAreaFreeSpecialist, "int ()") + .def("getGlobalFreeSpecialist", &CvBuildingInfo::getGlobalFreeSpecialist, "int ()") + .def("getHappiness", &CvBuildingInfo::getHappiness, "int ()") + .def("getAreaHappiness", &CvBuildingInfo::getAreaHappiness, "int ()") + .def("getGlobalHappiness", &CvBuildingInfo::getGlobalHappiness, "int ()") + .def("getStateReligionHappiness", &CvBuildingInfo::getStateReligionHappiness, "int ()") + .def("getWorkerSpeedModifier", &CvBuildingInfo::getWorkerSpeedModifier, "int ()") + .def("getMilitaryProductionModifier", &CvBuildingInfo::getMilitaryProductionModifier, "int ()") + .def("getSpaceProductionModifier", &CvBuildingInfo::getSpaceProductionModifier, "int ()") + .def("getGlobalSpaceProductionModifier", &CvBuildingInfo::getGlobalSpaceProductionModifier, "int ()") + .def("getTradeRoutes", &CvBuildingInfo::getTradeRoutes, "int ()") + .def("getCoastalTradeRoutes", &CvBuildingInfo::getCoastalTradeRoutes, "int ()") + .def("getGlobalTradeRoutes", &CvBuildingInfo::getGlobalTradeRoutes, "int ()") + .def("getTradeRouteModifier", &CvBuildingInfo::getTradeRouteModifier, "int ()") + .def("getForeignTradeRouteModifier", &CvBuildingInfo::getForeignTradeRouteModifier, "int ()") + .def("getAssetValue", &CvBuildingInfo::getAssetValue, "int ()") + .def("getPowerValue", &CvBuildingInfo::getPowerValue, "int ()") + .def("getSpecialBuildingType", &CvBuildingInfo::getSpecialBuildingType, "int ()") + .def("getAdvisorType", &CvBuildingInfo::getAdvisorType, "int ()") + .def("getHolyCity", &CvBuildingInfo::getHolyCity, "int ()") + .def("getReligionType", &CvBuildingInfo::getReligionType, "int ()") + .def("getStateReligion", &CvBuildingInfo::getStateReligion, "int ()") + .def("getPrereqReligion", &CvBuildingInfo::getPrereqReligion, "int ()") + .def("getPrereqCorporation", &CvBuildingInfo::getPrereqCorporation, "int ()") + .def("getFoundsCorporation", &CvBuildingInfo::getFoundsCorporation, "int ()") + .def("getGlobalReligionCommerce", &CvBuildingInfo::getGlobalReligionCommerce, "int ()") + .def("getGlobalCorporationCommerce", &CvBuildingInfo::getGlobalCorporationCommerce, "int ()") + .def("getPrereqAndBonus", &CvBuildingInfo::getPrereqAndBonus, "int ()") + .def("getGreatPeopleUnitClass", &CvBuildingInfo::getGreatPeopleUnitClass, "int ()") + .def("getGreatPeopleRateChange", &CvBuildingInfo::getGreatPeopleRateChange, "int ()") + .def("getConquestProbability", &CvBuildingInfo::getConquestProbability, "int ()") + .def("getMaintenanceModifier", &CvBuildingInfo::getMaintenanceModifier, "int ()") + .def("getWarWearinessModifier", &CvBuildingInfo::getWarWearinessModifier, "int ()") + .def("getGlobalWarWearinessModifier", &CvBuildingInfo::getGlobalWarWearinessModifier, "int ()") + .def("getEnemyWarWearinessModifier", &CvBuildingInfo::getEnemyWarWearinessModifier, "int ()") + .def("getHealRateChange", &CvBuildingInfo::getHealRateChange, "int ()") + .def("getHealth", &CvBuildingInfo::getHealth, "int ()") + .def("getAreaHealth", &CvBuildingInfo::getAreaHealth, "int ()") + .def("getGlobalHealth", &CvBuildingInfo::getGlobalHealth, "int ()") + .def("getGlobalPopulationChange", &CvBuildingInfo::getGlobalPopulationChange, "int ()") + .def("getFreeTechs", &CvBuildingInfo::getFreeTechs, "int ()") + .def("getDefenseModifier", &CvBuildingInfo::getDefenseModifier, "int ()") + .def("getBombardDefenseModifier", &CvBuildingInfo::getBombardDefenseModifier, "int ()") + .def("getAllCityDefenseModifier", &CvBuildingInfo::getAllCityDefenseModifier, "int ()") + .def("getEspionageDefenseModifier", &CvBuildingInfo::getEspionageDefenseModifier, "int ()") + .def("getMissionType", &CvBuildingInfo::getMissionType, "int ()") + .def("getVoteSourceType", &CvBuildingInfo::getVoteSourceType, "int ()") + + .def("isTeamShare", &CvBuildingInfo::isTeamShare, "bool ()") + .def("isWater", &CvBuildingInfo::isWater, "bool ()") + .def("isRiver", &CvBuildingInfo::isRiver, "bool ()") + .def("isPower", &CvBuildingInfo::isPower, "bool ()") + .def("isDirtyPower", &CvBuildingInfo::isDirtyPower, "bool ()") + .def("isAreaCleanPower", &CvBuildingInfo::isAreaCleanPower, "bool ()") + .def("isAreaBorderObstacle", &CvBuildingInfo::isAreaBorderObstacle, "bool ()") + .def("isForceTeamVoteEligible", &CvBuildingInfo::isForceTeamVoteEligible, "bool ()") + .def("isCapital", &CvBuildingInfo::isCapital, "bool ()") + .def("isGovernmentCenter", &CvBuildingInfo::isGovernmentCenter, "bool ()") + .def("isGoldenAge", &CvBuildingInfo::isGoldenAge, "bool ()") + .def("isMapCentering", &CvBuildingInfo::isMapCentering, "bool ()") + .def("isNoUnhappiness", &CvBuildingInfo::isNoUnhappiness, "bool ()") + .def("isNoUnhealthyPopulation", &CvBuildingInfo::isNoUnhealthyPopulation, "bool ()") + .def("isBuildingOnlyHealthy", &CvBuildingInfo::isBuildingOnlyHealthy, "bool ()") + .def("isNeverCapture", &CvBuildingInfo::isNeverCapture, "bool ()") + .def("isNukeImmune", &CvBuildingInfo::isNukeImmune, "bool ()") + .def("isPrereqReligion", &CvBuildingInfo::isPrereqReligion, "bool ()") + .def("isCenterInCity", &CvBuildingInfo::isCenterInCity, "bool ()") + .def("isStateReligion", &CvBuildingInfo::isStateReligion, "bool ()") + .def("isAllowsNukes", &CvBuildingInfo::isAllowsNukes, "bool ()") + + .def("getConstructSound", &CvBuildingInfo::getConstructSound, "string ()") + .def("getHotKey", &CvBuildingInfo::getHotKey, "string ()") + .def("getHotKeyDescription", &CvBuildingInfo::getHotKeyDescription, "string ()") + .def("getArtDefineTag", &CvBuildingInfo::getArtDefineTag, "string ()") + .def("getMovie", &CvBuildingInfo::getMovie, "string ()") + .def("getMovieDefineTag", &CvBuildingInfo::getMovieDefineTag, "string ()") + + + // Arrays + + .def("getYieldChange", &CvBuildingInfo::getYieldChange, "int (int i)") + .def("getYieldModifier", &CvBuildingInfo::getYieldModifier, "int (int i)") + .def("getPowerYieldModifier", &CvBuildingInfo::getPowerYieldModifier, "int (int i)") + .def("getGlobalYieldModifier", &CvBuildingInfo::getGlobalYieldModifier, "int (int i)") + .def("getSeaPlotYieldChange", &CvBuildingInfo::getSeaPlotYieldChange, "int (int i)") + .def("getRiverPlotYieldChange", &CvBuildingInfo::getRiverPlotYieldChange, "int (int i)") + .def("getGlobalSeaPlotYieldChange", &CvBuildingInfo::getGlobalSeaPlotYieldChange, "int (int i)") + .def("getCommerceChange", &CvBuildingInfo::getCommerceChange, "int (int i)") + .def("getObsoleteSafeCommerceChange", &CvBuildingInfo::getObsoleteSafeCommerceChange, "int (int i)") + .def("getCommerceChangeDoubleTime", &CvBuildingInfo::getCommerceChangeDoubleTime, "int (int i)") + .def("getCommerceModifier", &CvBuildingInfo::getCommerceModifier, "int (int i)") + .def("getGlobalCommerceModifier", &CvBuildingInfo::getGlobalCommerceModifier, "int (int i)") + .def("getStateReligionCommerce", &CvBuildingInfo::getStateReligionCommerce, "int (int i)") + .def("getCommerceHappiness", &CvBuildingInfo::getCommerceHappiness, "int (int i)") + .def("getReligionChange", &CvBuildingInfo::getReligionChange, "int (int i)") + .def("getSpecialistCount", &CvBuildingInfo::getSpecialistCount, "int (int i)") + .def("getFreeSpecialistCount", &CvBuildingInfo::getFreeSpecialistCount, "int (int i)") + .def("getBonusHealthChanges", &CvBuildingInfo::getBonusHealthChanges, "int (int i)") + .def("getBonusHappinessChanges", &CvBuildingInfo::getBonusHappinessChanges, "int (int i)") + .def("getBonusProductionModifier", &CvBuildingInfo::getBonusProductionModifier, "int (int i)") + .def("getUnitCombatFreeExperience", &CvBuildingInfo::getUnitCombatFreeExperience, "int (int i)") + .def("getDomainFreeExperience", &CvBuildingInfo::getDomainFreeExperience, "int (int i)") + .def("getDomainProductionModifier", &CvBuildingInfo::getDomainProductionModifier, "int (int i)") + .def("getPrereqAndTechs", &CvBuildingInfo::getPrereqAndTechs, "int (int i)") + .def("getPrereqOrBonuses", &CvBuildingInfo::getPrereqOrBonuses, "int (int i)") + .def("getProductionTraits", &CvBuildingInfo::getProductionTraits, "int (int i)") + .def("getHappinessTraits", &CvBuildingInfo::getHappinessTraits, "int (int i)") + .def("getBuildingHappinessChanges", &CvBuildingInfo::getBuildingHappinessChanges, "int (int i)") + .def("getPrereqNumOfBuildingClass", &CvBuildingInfo::getPrereqNumOfBuildingClass, "int (int i)") + .def("getFlavorValue", &CvBuildingInfo::getFlavorValue, "int (int i)") + .def("getImprovementFreeSpecialist", &CvBuildingInfo::getImprovementFreeSpecialist, "int (int i)") + + .def("isCommerceFlexible", &CvBuildingInfo::isCommerceFlexible, "bool (int i)") + .def("isCommerceChangeOriginalOwner", &CvBuildingInfo::isCommerceChangeOriginalOwner, "bool (int i)") + .def("isBuildingClassNeededInCity", &CvBuildingInfo::isBuildingClassNeededInCity, "bool (int i)") + + .def("getSpecialistYieldChange", &CvBuildingInfo::getSpecialistYieldChange, "int (int i, int j)") + .def("getBonusYieldModifier", &CvBuildingInfo::getBonusYieldModifier, "int (int i, int j)") + + .def("getArtInfo", &CvBuildingInfo::getArtInfo, python::return_value_policy()) + ; + + python::class_ >("CvSpecialBuildingInfo") + .def("getObsoleteTech", &CvSpecialBuildingInfo::getObsoleteTech, "int ()") + .def("getTechPrereq", &CvSpecialBuildingInfo::getTechPrereq, "int ()") + .def("isValid", &CvSpecialBuildingInfo::isValid, "bool ()") + + // Arrays + + .def("getProductionTraits", &CvSpecialBuildingInfo::getProductionTraits, "int (int i)") + ; +} diff --git a/Mod/Observer/Assets/CvGameCoreDLL.dll b/Mod/Observer/Assets/CvGameCoreDLL.dll index 6780438..d472993 100644 Binary files a/Mod/Observer/Assets/CvGameCoreDLL.dll and b/Mod/Observer/Assets/CvGameCoreDLL.dll differ diff --git a/Mod/Observer/Assets/Python/CvGameInterface.py b/Mod/Observer/Assets/Python/CvGameInterface.py new file mode 100644 index 0000000..5b65177 --- /dev/null +++ b/Mod/Observer/Assets/Python/CvGameInterface.py @@ -0,0 +1,510 @@ +## Sid Meier's Civilization 4 +## Copyright Firaxis Games 2005 +## +## ##### WARNING - MODIFYING THE FUNCTION NAMES OF THIS FILE IS PROHIBITED ##### +## +## The app specifically calls the functions as they are named. Use this file to pass +## args to another file that contains your modifications +## +## MODDERS - If you create a GameUtils file, update the CvGameInterfaceFile reference to point to your new file + +# +import CvUtil +import CvGameUtils +import CvGameInterfaceFile +import CvEventInterface +from CvPythonExtensions import * + +# novice: +# Added imports for getGameStateString: +import string +import time +from PyHelpers import PyGame, PyPlayer + +# globals +gc = CyGlobalContext() +normalGameUtils = CvGameInterfaceFile.GameUtils + +# novice: Added entry point getGameStateString to be called from the C++ code. +def getGameStateString(argslist): + try: + #print("Dumping game state...") + religionCount = 7 + buildingCount = 159 + promotionTypeCount = 54 + specialistTypeCount = 14 + technologyCount = gc.getNumTechInfos() + cyMap = CyMap() + cyGame = CyGame() + pyGame = PyGame() + #testvar = 123/0 + plots = [] + players = [] + #print(".Dumping player state...") + for p in pyGame.getCivPlayerList(): + team = p.getTeam() + pp = p.getPlayer() + contacts = [] + #print("..Dumping player " + str(p.getID()) + " contacts...") + for op in range(gc.getMAX_CIV_PLAYERS()): + if pp.canContact(op): + contacts.append(op) + #print("..Dumping player " + str(p.getID()) + " techs...") + techProgress = [] + for t in range(technologyCount-1): + techProgress.append(team.getResearchProgress(t)) + cities = [] + #print("..Dumping player " + str(p.getID()) + " cities...") + for c in p.getCityList(): + cc = c.GetCy() + buildings = [] + buildQueue = [] + religions = [] + holyCities = [] + freeSpecialists = [] + specialists = [] + for s in range(specialistTypeCount-1): + for i in range(cc.getAddedFreeSpecialistCount(s)): + freeSpecialists.append(s) + for i in range(cc.getSpecialistCount(s)): + specialists.append(s) + for r in range(religionCount-1): + if(cc.isHasReligion(r)): + religions.append(r) + if(cc.isHolyCityByType(r)): + holyCities.append(r) + for b in range(buildingCount-1): + if cc.getNumBuilding(b) > 0: + buildings.append(b) + for q in range(cc.getOrderQueueLength()): + order = cc.getOrderFromQueue(q) + buildQueue.append({"save": order.bSave, "type": int(order.eOrderType), "data1": order.iData1, "data2": order.iData2}) + cities.append({ + "ID": c.getID(), + "x": c.getX(), + "y": c.getY(), + #"index": c.getIndex(), + "name": c.getName().replace("'", ""), + "owner": c.getOwner(), + "isBarbarian" : c.isBarbarian(), + "size" : c.getPopulation(), + "maintenance" : { "colony": cc.calculateColonyMaintenanceTimes100(), "distance": cc.calculateDistanceMaintenanceTimes100(), "numCities": cc.calculateNumCitiesMaintenanceTimes100(), "corps" : cc.calculateCorporationMaintenanceTimes100() }, + "food" : { "fpt": cc.getYieldRate(0), "food" : cc.getFood(), "difference" : cc.foodDifference(False), "foodKept" : cc.getFoodKept(), "foodTurnsLeft" : cc.getFoodTurnsLeft() }, + "happy" : { "espionageCounter": cc.getEspionageHappinessCounter(), "extra": cc.getExtraHappiness(), "totalHappy" : cc.happyLevel(), "angryPopulation" : cc.angryPopulation(0) }, #"fromBuildings" : cc.getBuildingHappiness(), "fromReligionGood": cc.getReligionGoodHappiness(), "fromReligionBad": cc.getReligionBadHappiness() }, # "totalGood": cc.calculateTotalCityHappiness(), "totalBad": cc.calculateTotalCityUnhappiness(), + "health" : { "espionageCounter": cc.getEspionageHealthCounter(), "goodHealth": cc.goodHealth(), "badHealth" : cc.badHealth(false), "fromResourcesGood" : cc.getBonusGoodHealth(), "fromResourcesBad" : cc.getBonusBadHealth(), "extra" : cc.getExtraHealth(), "fromBuildingsGood" : cc.getBuildingGoodHealth(), "fromBuildingsBad" : cc.getBuildingBadHealth()}, # "totalGood": cc.calculateTotalCityHealthiness (), "totalBad": cc.calculateTotalCityUnhealthiness(), + "production" : { "hpt": cc.getYieldRate(1), "isFood" : cc.isFoodProduction(), "overflow" : cc.getOverflowProduction(), "hammersInBox" : cc.getProduction(), "hammersNeeded" : cc.getProductionNeeded(), "name" : cc.getProductionName(), "process": cc.getProductionProcess(), "project": cc.getProductionProject(), "building": cc.getProductionBuilding(), "unit" : cc.getProductionUnit(), "turnsLeft": cc.getProductionTurnsLeft()}, + "commerce" : { "cpt" : cc.getYieldRate(2) }, + "specialists": specialists, + "freeSpecialists": freeSpecialists, + "buildings": buildings, + "buildQueue": buildQueue, + "religions": religions, + "holyCities": holyCities + }) + #print("..Dumping player " + str(p.getID()) + " player info...") + currentResearch = pp.getCurrentResearch() + currentTechTurnsLeft = 0 + if currentResearch >= 0: + currentTechTurnsLeft = pp.getResearchTurnsLeft(currentResearch, True) + players.append({ + "isAlive" : p.isAlive(), + "ID" : p.getID(), + "name" : p.getName(), + "handicap" : int(pp.getHandicapType()), + "color" : pp.getPlayerColor(), + "team" : p.getTeamID(), + "contacts" : contacts, + "civics" : p.getCurrentCivicList(), + "gold" : p.getGold(), + "maintenanceCosts" : p.getTotalMaintenance(), + "unitCosts": p.calculateUnitCost(), + "unitSupply" : p.calculateUnitSupply(), + "goldCommerceRate" : p.getGoldCommerceRate(), + "researchCommerceRate" : p.getResearchCommerceRate(), + "cultureCommerceRate" : p.getCultureCommerceRate(), + "espionageCommerceRate" : pp.getCommerceRate(CommerceTypes.COMMERCE_ESPIONAGE), + "beakersPerTurn" : p.calculateResearchRate(), + "goldPerTurn" : p.getGoldPerTurn(), + "techs" : p.getResearchedTechList(), + "techProgress" : techProgress, + "currentTechName" : p.getCurrentTechName(), + "currentTech" : currentResearch, + "overflowResearch" : pp.getOverflowResearch(), + "currentTechTurnsLeft" : currentTechTurnsLeft, + "civType" : pp.getCivilizationType(), + "civDescription" : p.getCivDescription().replace("'", ""), + "civName" : p.getCivilizationName().replace("'", ""), + "civShortDescription" : p.getCivilizationShortDescription().replace("'", ""), + "civAdjective": p.getCivilizationAdjective().replace("'", ""), + "leaderName" : p.getLeaderName().replace("'", ""), + "leaderType": p.getLeaderType(), + "sliders": { "gold": pp.getCommercePercent(0), "research": pp.getCommercePercent(1), "culture": pp.getCommercePercent(2), "espionage": pp.getCommercePercent(3) }, + "cities": cities + }) + #print(".Dumping map state...") + for x in range(cyMap.getGridWidth()): + for y in range(cyMap.getGridHeight()): + plot = cyMap.plot(x, y) + wc = plot.getWorkingCity() + wcid = -1 + if not wc is None: + wcid = wc.getID() + visible = [] + revealed = [] + culture = [] + units = [] + for u in range(plot.getNumUnits()): + unit = plot.getUnit(u) + transportUnitID = -1 + if(not unit.getTransportUnit() is None): + transportUnitID = unit.getTransportUnit().getID() + promotions = [] + for pr in range(promotionTypeCount-1): + if unit.isHasPromotion(pr): + promotions.append(pr) + units.append({ + "cargo": unit.getCargo(), + "damage": unit.getDamage(), + "buildType" : int(unit.getBuildType()), + "xp": unit.getExperience(), + "level": unit.getLevel(), + "name" : unit.getName(), + "moves" : unit.getMoves(), + "owner" : unit.getOwner(), + "ID" : unit.getID(), + "transportUnit" : transportUnitID, + "unitType" : unit.getUnitType(), + "fortifyTurns" : unit.getFortifyTurns(), + "promotions": promotions + }) + for p in range(len(players)): + culture.append(plot.getCulture(p)) + for t in range(cyGame.countCivTeamsEverAlive()): + revealed.append(plot.isRevealed(t, False)) + visible.append(plot.isVisible(t, False)) + plots.append({"x": x, "y": y, + "wcid": wcid, + "worked": plot.isBeingWorked(), + "bonus": plot.getBonusType(plot.getTeam()), + "terrain": plot.getTerrainType(), + "improvement": plot.getImprovementType(), + "feature": { "type" : plot.getFeatureType(), "variety": plot.getFeatureVariety() }, + "river" : { "id" : plot.getRiverID(), "isNOfRiver" : plot.isNOfRiver(), "isWOfRiver": plot.isWOfRiver(), "isRiverSide" : plot.isRiverSide(), "nsDir" : int(plot.getRiverNSDirection()), "weDir" : int(plot.getRiverWEDirection()) }, + "isGoody": plot.isGoody(), + "isImpassable" : plot.isImpassable(), + "isFreshWater" : plot.isFreshWater(), + "isIrrigated" : plot.isIrrigated(), + "routeType" : plot.getRouteType(), + "plotType" : int(plot.getPlotType()), + "visible": visible, + "revealed": revealed, + "culture" : culture, + "owner" : plot.calculateCulturalOwner(), + "units" : units + }) + #print(".Dumping game settings state...") + jsondata = { + "game": { + "name": cyGame.getName().replace("'", ""), + "turn": cyGame.getGameTurn(), + "year": cyGame.getGameTurnYear(), + "isCircumnavigated" : cyGame.isCircumnavigated(), + "speed" : int(cyGame.getGameSpeedType()), + "startEra" : int(cyGame.getStartEra()), + "playerCount" : cyGame.countCivPlayersEverAlive(), + "isPbem" : cyGame.isPbem(), + "isPitboss" : cyGame.isPitboss(), + "isPitbossHost" : cyGame.isPitbossHost() + }, + "players" : players, + "map": { + "isWrapX" : cyMap.isWrapX(), + "isWrapY" : cyMap.isWrapY(), + "width" : cyMap.getGridWidth(), + "height" : cyMap.getGridHeight(), + "worldSize" : int(cyMap.getWorldSize()), + "plots": plots + } + } + #print(".Creating json file...") + #print(".Using file name " + filename + "...") + jsonstring = str(jsondata) + jsonstring = jsonstring.replace(": u'", ": \"") + jsonstring = jsonstring.replace("'", "\"") + jsonstring = jsonstring.replace("False", "false") + jsonstring = jsonstring.replace("True", "true") + jsonstring = jsonstring.replace("}", "}\n") + return jsonstring + except Exception, err: + return "{ \"error\": \"" + str(err) + "\" }" + +def gameUtils(): + ' replace normalGameUtils with your mod version' + return normalGameUtils + +def isVictoryTest(): + #CvUtil.pyPrint( "CvGameInterface.isVictoryTest" ) + return gameUtils().isVictoryTest() + +def isVictory(argsList): + return gameUtils().isVictory(argsList) + +def isPlayerResearch(argsList): + #CvUtil.pyPrint( "CvGameInterface.isPlayerResearch" ) + return gameUtils().isPlayerResearch(argsList) + +def getExtraCost(argsList): + #CvUtil.pyPrint( "CvGameInterface.getExtraCost" ) + return gameUtils().getExtraCost(argsList) + +def createBarbarianCities(): + #CvUtil.pyPrint( "CvGameInterface.createBarbarianCities" ) + return gameUtils().createBarbarianCities() + +def createBarbarianUnits(): + #CvUtil.pyPrint( "CvGameInterface.createBarbarianUnits" ) + return gameUtils().createBarbarianUnits() + +def skipResearchPopup(argsList): + #CvUtil.pyPrint( "CvGameInterface.skipResearchPopup" ) + return gameUtils().skipResearchPopup(argsList) + +def showTechChooserButton(argsList): + #CvUtil.pyPrint( "CvGameInterface.showTechChooserButton" ) + return gameUtils().showTechChooserButton(argsList) + +def getFirstRecommendedTech(argsList): + #CvUtil.pyPrint( "CvGameInterface.getFirstRecommendedTech" ) + return gameUtils().getFirstRecommendedTech(argsList) + +def getSecondRecommendedTech(argsList): + #CvUtil.pyPrint( "CvGameInterface.getSecondRecommendedTech" ) + return gameUtils().getSecondRecommendedTech(argsList) + +def skipProductionPopup(argsList): + #CvUtil.pyPrint( "CvGameInterface.skipProductionPopup" ) + return gameUtils().skipProductionPopup(argsList) + +def canRazeCity(argsList): + #CvUtil.pyPrint( "CvGameInterface.canRazeCity" ) + return gameUtils().canRazeCity(argsList) + +def canDeclareWar(argsList): + #CvUtil.pyPrint( "CvGameInterface.canRazeCity" ) + return gameUtils().canDeclareWar(argsList) + +def showExamineCityButton(argsList): + #CvUtil.pyPrint( "CvGameInterface.showExamineCityButton" ) + return gameUtils().showExamineCityButton(argsList) + +def getRecommendedUnit(argsList): + #CvUtil.pyPrint( "CvGameInterface.getRecommendedUnit" ) + return gameUtils().getRecommendedUnit(argsList) + +def getRecommendedBuilding(argsList): + #CvUtil.pyPrint( "CvGameInterface.getRecommendedBuilding" ) + return gameUtils().getRecommendedBuilding(argsList) + +def updateColoredPlots(): + #CvUtil.pyPrint( "CvGameInterface.updateColoredPlots" ) + return gameUtils().updateColoredPlots() + +def isActionRecommended(argsList): + #CvUtil.pyPrint( "CvGameInterface.isActionRecommended" ) + return gameUtils().isActionRecommended(argsList) + +def unitCannotMoveInto(argsList): + return gameUtils().unitCannotMoveInto(argsList) + +def cannotHandleAction(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotHandleAction" ) + return gameUtils().cannotHandleAction(argsList) + +def canBuild(argsList): + #CvUtil.pyPrint( "CvGameInterface.canBuild" ) + return gameUtils().canBuild(argsList) + +def cannotFoundCity(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotHandleAction" ) + return gameUtils().cannotFoundCity(argsList) + +def cannotSelectionListMove(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotSelectionListMove" ) + return gameUtils().cannotSelectionListMove(argsList) + +def cannotSelectionListGameNetMessage(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotSelectionListGameNetMessage" ) + return gameUtils().cannotSelectionListGameNetMessage(argsList) + +def cannotDoControl(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotDoControl" ) + return gameUtils().cannotDoControl(argsList) + +def canResearch(argsList): + #CvUtil.pyPrint( "CvGameInterface.canResearch" ) + return gameUtils().canResearch(argsList) + +def cannotResearch(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotResearch" ) + return gameUtils().cannotResearch(argsList) + +def canDoCivic(argsList): + #CvUtil.pyPrint( "CvGameInterface.canDoCivic" ) + return gameUtils().canDoCivic(argsList) + +def cannotDoCivic(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotDoCivic" ) + return gameUtils().cannotDoCivic(argsList) + +def canTrain(argsList): + #CvUtil.pyPrint( "CvGameInterface.canTrain" ) + return gameUtils().canTrain(argsList) + +def cannotTrain(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotTrain" ) + return gameUtils().cannotTrain(argsList) + +def canConstruct(argsList): + #CvUtil.pyPrint( "CvGameInterface.canConstruct" ) + return gameUtils().canConstruct(argsList) + +def cannotConstruct(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotConstruct" ) + return gameUtils().cannotConstruct(argsList) + +def canCreate(argsList): + #CvUtil.pyPrint( "CvGameInterface.canCreate" ) + return gameUtils().canCreate(argsList) + +def cannotCreate(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotCreate" ) + return gameUtils().cannotCreate(argsList) + +def canMaintain(argsList): + #CvUtil.pyPrint( "CvGameInterface.canMaintain" ) + return gameUtils().canMaintain(argsList) + +def cannotMaintain(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotMaintain" ) + return gameUtils().cannotMaintain(argsList) + +def AI_chooseTech(argsList): + 'AI chooses what to research' + #CvUtil.pyPrint( "CvGameInterface.AI_chooseTech" ) + return gameUtils().AI_chooseTech(argsList) + +def AI_chooseProduction(argsList): + 'AI chooses city production' + #CvUtil.pyPrint( "CvGameInterface.AI_chooseProduction" ) + return gameUtils().AI_chooseProduction(argsList) + +def AI_unitUpdate(argsList): + 'AI moves units - return 0 to let AI handle it, return 1 to say that the move is handled in python ' + #CvUtil.pyPrint( "CvGameInterface.AI_unitUpdate" ) + return gameUtils().AI_unitUpdate(argsList) + +def AI_doWar(argsList): + 'AI decides whether to make war or peace - return 0 to let AI handle it, return 1 to say that the move is handled in python ' + #CvUtil.pyPrint( "CvGameInterface.AI_doWar" ) + return gameUtils().AI_doWar(argsList) + +def AI_doDiplo(argsList): + 'AI decides does diplomacy for the turn - return 0 to let AI handle it, return 1 to say that the move is handled in python ' + #CvUtil.pyPrint( "CvGameInterface.AI_doDiplo" ) + return gameUtils().AI_doDiplo(argsList) + +def calculateScore(argsList): + return gameUtils().calculateScore(argsList) + +def doHolyCity(): + #CvUtil.pyPrint( "CvGameInterface.doHolyCity" ) + return gameUtils().doHolyCity() + +def doHolyCityTech(argsList): + #CvUtil.pyPrint( "CvGameInterface.doHolyCityTech" ) + return gameUtils().doHolyCityTech(argsList) + +def doGold(argsList): + #CvUtil.pyPrint( "CvGameInterface.doGold" ) + return gameUtils().doGold(argsList) + +def doResearch(argsList): + #CvUtil.pyPrint( "CvGameInterface.doResearch" ) + return gameUtils().doResearch(argsList) + +def doGoody(argsList): + #CvUtil.pyPrint( "CvGameInterface.doGoody" ) + return gameUtils().doGoody(argsList) + +def doGrowth(argsList): + #CvUtil.pyPrint( "CvGameInterface.doGrowth" ) + return gameUtils().doGrowth(argsList) + +def doProduction(argsList): + #CvUtil.pyPrint( "CvGameInterface.doProduction" ) + return gameUtils().doProduction(argsList) + +def doCulture(argsList): + #CvUtil.pyPrint( "CvGameInterface.doCulture" ) + return gameUtils().doCulture(argsList) + +def doPlotCulture(argsList): + #CvUtil.pyPrint( "CvGameInterface.doPlotCulture" ) + return gameUtils().doPlotCulture(argsList) + +def doReligion(argsList): + #CvUtil.pyPrint( "CvGameInterface.doReligion" ) + return gameUtils().doReligion(argsList) + +def doGreatPeople(argsList): + #CvUtil.pyPrint( "CvGameInterface.doGreatPeople" ) + return gameUtils().doGreatPeople(argsList) + +def doMeltdown(argsList): + #CvUtil.pyPrint( "CvGameInterface.doMeltdown" ) + return gameUtils().doMeltdown(argsList) + +def doReviveActivePlayer(argsList): + return gameUtils().doReviveActivePlayer(argsList) + +def doPillageGold(argsList): + return gameUtils().doPillageGold(argsList) + +def doCityCaptureGold(argsList): + return gameUtils().doCityCaptureGold(argsList) + +def citiesDestroyFeatures(argsList): + return gameUtils().citiesDestroyFeatures(argsList) + +def canFoundCitiesOnWater(argsList): + return gameUtils().canFoundCitiesOnWater(argsList) + +def doCombat(argsList): + return gameUtils().doCombat(argsList) + +def getConscriptUnitType(argsList): + return gameUtils().getConscriptUnitType(argsList) + +def getCityFoundValue(argsList): + return gameUtils().getCityFoundValue(argsList) + +def canPickPlot(argsList): + return gameUtils().canPickPlot(argsList) + +def getUnitCostMod(argsList): + return gameUtils().getUnitCostMod(argsList) + +def getBuildingCostMod(argsList): + return gameUtils().getBuildingCostMod(argsList) + +def canUpgradeAnywhere(argsList): + return gameUtils().canUpgradeAnywhere(argsList) + +def getWidgetHelp(argsList): + return gameUtils().getWidgetHelp(argsList) + +def getUpgradePriceOverride(argsList): + return gameUtils().getUpgradePriceOverride(argsList) + +def getExperienceNeeded(argsList): + return gameUtils().getExperienceNeeded(argsList) \ No newline at end of file diff --git a/Mod/Observer/Assets/XML/Civilizations/CIV4CivilizationInfos.xml b/Mod/Observer/Assets/XML/Civilizations/CIV4CivilizationInfos.xml new file mode 100644 index 0000000..cc32b31 --- /dev/null +++ b/Mod/Observer/Assets/XML/Civilizations/CIV4CivilizationInfos.xml @@ -0,0 +1,4706 @@ + + + + + + + + + + + CIVILIZATION_AMERICA + TXT_KEY_CIV_AMERICA_DESC + TXT_KEY_CIV_AMERICA_SHORT_DESC + TXT_KEY_CIV_AMERICA_ADJECTIVE + TXT_KEY_CIV_AMERICA_PEDIA + PLAYERCOLOR_BLUE + ART_DEF_CIVILIZATION_AMERICA + ARTSTYLE_EUROPEAN + UNIT_ARTSTYLE_EUROPEAN + 1 + 1 + + TXT_KEY_CITY_NAME_WASHINGTON + TXT_KEY_CITY_NAME_NEW_YORK + TXT_KEY_CITY_NAME_BOSTON + TXT_KEY_CITY_NAME_PHILADELPHIA + TXT_KEY_CITY_NAME_ATLANTA + TXT_KEY_CITY_NAME_CHICAGO + TXT_KEY_CITY_NAME_SEATTLE + TXT_KEY_CITY_NAME_SAN_FRANCISCO + TXT_KEY_CITY_NAME_LOS_ANGELES + TXT_KEY_CITY_NAME_HOUSTON + TXT_KEY_CITY_NAME_PORTLAND + TXT_KEY_CITY_NAME_ST_LOUIS + TXT_KEY_CITY_NAME_MIAMI + TXT_KEY_CITY_NAME_BUFFALO + TXT_KEY_CITY_NAME_DETROIT + TXT_KEY_CITY_NAME_NEW_ORLEANS + TXT_KEY_CITY_NAME_BALTIMORE + TXT_KEY_CITY_NAME_DENVER + TXT_KEY_CITY_NAME_CINCINNATI + TXT_KEY_CITY_NAME_DALLAS + TXT_KEY_CITY_NAME_MEMPHIS + TXT_KEY_CITY_NAME_CLEVELAN + TXT_KEY_CITY_NAME_KANSAS_CITY + TXT_KEY_CITY_NAME_SAN_DIEGO + TXT_KEY_CITY_NAME_RICHMOND + TXT_KEY_CITY_NAME_LAS_VEGAS + TXT_KEY_CITY_NAME_PHOENIX + TXT_KEY_CITY_NAME_ALBUQUERQUE + TXT_KEY_CITY_NAME_MINNEAPOLIS + TXT_KEY_CITY_NAME_PITTSBURGH + TXT_KEY_CITY_NAME_OAKLAND + TXT_KEY_CITY_NAME_TAMPA_BAY + TXT_KEY_CITY_NAME_ORLANDO + TXT_KEY_CITY_NAME_TACOMA + TXT_KEY_CITY_NAME_SANTA_FE + TXT_KEY_CITY_NAME_OLYMPIA + TXT_KEY_CITY_NAME_HUNT_VALLEY + TXT_KEY_CITY_NAME_SPRINGFIELD + TXT_KEY_CITY_NAME_PALO_ALTO + TXT_KEY_CITY_NAME_CENTRALIA + TXT_KEY_CITY_NAME_SPOKANE + TXT_KEY_CITY_NAME_JACKSONVILLE + TXT_KEY_CITY_NAME_SAVANNAH + TXT_KEY_CITY_NAME_CHARLESTON + TXT_KEY_CITY_NAME_SAN_ANTONIO + TXT_KEY_CITY_NAME_OMAHA + TXT_KEY_CITY_NAME_BIRMINGHAM + TXT_KEY_CITY_NAME_HONOLULU + TXT_KEY_CITY_NAME_ANCHORAGE + TXT_KEY_CITY_NAME_SACRAMENTO + TXT_KEY_CITY_NAME_SALT_LAKE_CITY + TXT_KEY_CITY_NAME_RENO + TXT_KEY_CITY_NAME_BOISE + TXT_KEY_CITY_NAME_MILWAUKEE + TXT_KEY_CITY_NAME_SANTA_CRUZ + TXT_KEY_CITY_NAME_MONTEREY + TXT_KEY_CITY_NAME_SANTA_MONICA + TXT_KEY_CITY_NAME_LITTLE_ROCK + TXT_KEY_CITY_NAME_COLUMBUS + TXT_KEY_CITY_NAME_LE_BAM + + + + BUILDINGCLASS_SUPERMARKET + BUILDING_AMERICAN_MALL + + + + + UNITCLASS_MARINE + UNIT_AMERICAN_NAVY_SEAL + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_FISHING + 1 + + + TECH_AGRICULTURE + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_WASHINGTON + 1 + + + LEADER_FRANKLIN_ROOSEVELT + 1 + + + LEADER_LINCOLN + 1 + + + NONE + AS3D_AMERICA_SELECT + AS3D_AMERICA_ORDER + + + + CIVILIZATION_ARABIA + TXT_KEY_CIV_ARABIA_DESC + TXT_KEY_CIV_ARABIA_SHORT_DESC + TXT_KEY_CIV_ARABIA_ADJECTIVE + TXT_KEY_CIV_ARABIA_PEDIA + PLAYERCOLOR_LIGHT_GREEN + ART_DEF_CIVILIZATION_ARABIA + ARTSTYLE_MIDDLE_EAST + UNIT_ARTSTYLE_MIDDLE_EAST + 1 + 1 + + TXT_KEY_CITY_NAME_MECCA + TXT_KEY_CITY_NAME_MEDINA + TXT_KEY_CITY_NAME_DAMASCUS + TXT_KEY_CITY_NAME_BAGHDAD + TXT_KEY_CITY_NAME_NAJRAN + TXT_KEY_CITY_NAME_KUFAH + TXT_KEY_CITY_NAME_BASRA + TXT_KEY_CITY_NAME_KHURASAN + TXT_KEY_CITY_NAME_ANJAR + TXT_KEY_CITY_NAME_FUSTAT + TXT_KEY_CITY_NAME_ADEN + TXT_KEY_CITY_NAME_YAMAMA + TXT_KEY_CITY_NAME_MUSCAT + TXT_KEY_CITY_NAME_MANSURA + TXT_KEY_CITY_NAME_BUKHARA + TXT_KEY_CITY_NAME_FEZ + TXT_KEY_CITY_NAME_SHIRAZ + TXT_KEY_CITY_NAME_MERW + TXT_KEY_CITY_NAME_BALKH + TXT_KEY_CITY_NAME_MOSUL + TXT_KEY_CITY_NAME_AYDAB + TXT_KEY_CITY_NAME_BAYT_RAS + TXT_KEY_CITY_NAME_SUHAR + TXT_KEY_CITY_NAME_TAIF + TXT_KEY_CITY_NAME_HAMA + TXT_KEY_CITY_NAME_TABUK + TXT_KEY_CITY_NAME_SANAA + TXT_KEY_CITY_NAME_SHIHR + TXT_KEY_CITY_NAME_TRIPOLI + TXT_KEY_CITY_NAME_TUNIS + TXT_KEY_CITY_NAME_KAIROUAN + TXT_KEY_CITY_NAME_ALGIERS + TXT_KEY_CITY_NAME_ORAN + TXT_KEY_CITY_NAME_TANGIER + TXT_KEY_CITY_NAME_CASABLANCA + TXT_KEY_CITY_NAME_MARRAKECH + + + + BUILDINGCLASS_LIBRARY + BUILDING_ARABIAN_MADRASSA + + + + + UNITCLASS_KNIGHT + UNIT_ARABIA_CAMELARCHER + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_THE_WHEEL + 1 + + + TECH_MYSTICISM + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_SALADIN + 1 + + + NONE + AS3D_ARABIA_SELECT + AS3D_ARABIA_ORDER + + + + CIVILIZATION_AZTEC + TXT_KEY_CIV_AZTEC_DESC + TXT_KEY_CIV_AZTEC_SHORT_DESC + TXT_KEY_CIV_AZTEC_ADJECTIVE + TXT_KEY_CIV_AZTEC_PEDIA + PLAYERCOLOR_GREEN + ART_DEF_CIVILIZATION_AZTEC + ARTSTYLE_SOUTH_AMERICA + UNIT_ARTSTYLE_SOUTH_AMERICA + 1 + 1 + + TXT_KEY_CITY_NAME_TENOCHTITLAN + TXT_KEY_CITY_NAME_TEOTIHUACAN + TXT_KEY_CITY_NAME_TLATELOLCO + TXT_KEY_CITY_NAME_TEXCOCO + TXT_KEY_CITY_NAME_TLAXCALA + TXT_KEY_CITY_NAME_CALIXTLAHUACA + TXT_KEY_CITY_NAME_XOCHICALCO + TXT_KEY_CITY_NAME_TLACOPAN + TXT_KEY_CITY_NAME_ATZCAPOTZALCO + TXT_KEY_CITY_NAME_TZINTZUNTZEN + TXT_KEY_CITY_NAME_MALINALCO + TXT_KEY_CITY_NAME_TULA + TXT_KEY_CITY_NAME_TAMUIN + TXT_KEY_CITY_NAME_TEAYO + TXT_KEY_CITY_NAME_CEMPOALA + TXT_KEY_CITY_NAME_CHALCO + TXT_KEY_CITY_NAME_TLALMANALCO + TXT_KEY_CITY_NAME_IXTAPALUCA + TXT_KEY_CITY_NAME_HUEXOTLA + TXT_KEY_CITY_NAME_TEPEXPAN + TXT_KEY_CITY_NAME_TEPETLAOXTOC + TXT_KEY_CITY_NAME_CHICONAUTLA + TXT_KEY_CITY_NAME_ZITLALTEPEC + TXT_KEY_CITY_NAME_COYOTEPEC + TXT_KEY_CITY_NAME_TEQUIXQUIAC + TXT_KEY_CITY_NAME_JILOTZINGO + TXT_KEY_CITY_NAME_TLAPANALOYA + TXT_KEY_CITY_NAME_TULTITAN + TXT_KEY_CITY_NAME_ECATEPEC + TXT_KEY_CITY_NAME_COATEPEC + TXT_KEY_CITY_NAME_CHALCHIUITES + TXT_KEY_CITY_NAME_CHIAUHITA + TXT_KEY_CITY_NAME_CHAPULTEPEC + TXT_KEY_CITY_NAME_ITZAPALAPA + TXT_KEY_CITY_NAME_AYOTZINCO + TXT_KEY_CITY_NAME_IZTAPAM + + + + BUILDINGCLASS_COURTHOUSE + BUILDING_AZTEC_SACRIFICIAL_ALTAR + + + + + UNITCLASS_SWORDSMAN + UNIT_AZTEC_JAGUAR + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_MYSTICISM + 1 + + + TECH_HUNTING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_MONTEZUMA + 1 + + + CIVILIZATION_AMERICA + AS3D_AZTEC_SELECT + AS3D_AZTEC_ORDER + + + + CIVILIZATION_BABYLON + TXT_KEY_CIV_BABYLON_DESC + TXT_KEY_CIV_BABYLON_SHORT_DESC + TXT_KEY_CIV_BABYLON_ADJECTIVE + TXT_KEY_CIV_BABYLON_PEDIA + PLAYERCOLOR_MIDDLE_PURPLE + ART_DEF_CIVILIZATION_BABYLON + ARTSTYLE_MIDDLE_EAST + UNIT_ARTSTYLE_MIDDLE_EAST + 1 + 1 + + TXT_KEY_CITY_NAME_BABYLON + TXT_KEY_CITY_NAME_AKKAD + TXT_KEY_CITY_NAME_DUR_KURIGALZU + TXT_KEY_CITY_NAME_NIPPUR + TXT_KEY_CITY_NAME_BORSIPPA + TXT_KEY_CITY_NAME_SIPPAR + TXT_KEY_CITY_NAME_OPIS + TXT_KEY_CITY_NAME_MARI + TXT_KEY_CITY_NAME_SHUSHAN + TXT_KEY_CITY_NAME_ESHNUNNA + TXT_KEY_CITY_NAME_ELLASAR + TXT_KEY_CITY_NAME_ERECH + TXT_KEY_CITY_NAME_KUTHA + TXT_KEY_CITY_NAME_SIRPURLA + TXT_KEY_CITY_NAME_NERIBTUM + TXT_KEY_CITY_NAME_ASHUR + TXT_KEY_CITY_NAME_NINEVEH + TXT_KEY_CITY_NAME_NIMRUD + TXT_KEY_CITY_NAME_ARBELA + TXT_KEY_CITY_NAME_NUZI + TXT_KEY_CITY_NAME_TUTUB + TXT_KEY_CITY_NAME_ARRAPKHA + TXT_KEY_CITY_NAME_SHADUPPUM + TXT_KEY_CITY_NAME_RAPIQUM + TXT_KEY_CITY_NAME_MASHKAN_SHAPIR + TXT_KEY_CITY_NAME_TUTTUL + TXT_KEY_CITY_NAME_RAMADI + TXT_KEY_CITY_NAME_ANA + TXT_KEY_CITY_NAME_HARADUM + TXT_KEY_CITY_NAME_AGRAB + TXT_KEY_CITY_NAME_UQAIR + TXT_KEY_CITY_NAME_GUBBA + TXT_KEY_CITY_NAME_HAFRIYAT + TXT_KEY_CITY_NAME_NAGAR + TXT_KEY_CITY_NAME_SHUBAT_ENLIL + TXT_KEY_CITY_NAME_URHAI + TXT_KEY_CITY_NAME_URKESH + TXT_KEY_CITY_NAME_AWAN + TXT_KEY_CITY_NAME_RIBLAH + TXT_KEY_CITY_NAME_TAYMA + + + + BUILDINGCLASS_COLOSSEUM + BUILDING_BABYLON_GARDEN + + + + + UNITCLASS_ARCHER + UNIT_BABYLON_BOWMAN + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_AGRICULTURE + 1 + + + TECH_THE_WHEEL + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_HAMMURABI + 1 + + + CIVILIZATION_PERSIA + AS3D_BABYLON_SELECT + AS3D_BABYLON_ORDER + + + + CIVILIZATION_BYZANTIUM + TXT_KEY_CIV_BYZANTIUM_DESC + TXT_KEY_CIV_BYZANTIUM_SHORT_DESC + TXT_KEY_CIV_BYZANTIUM_ADJECTIVE + TXT_KEY_CIV_BYZANTIUM_PEDIA + PLAYERCOLOR_DARK_GRAY + ART_DEF_CIVILIZATION_BYZANTIUM + ARTSTYLE_GRECO_ROMAN + UNIT_ARTSTYLE_GRECO_ROMAN + 1 + 1 + + TXT_KEY_CITY_NAME_CONSTANTINOPLE + TXT_KEY_CITY_NAME_THESSALONICA + TXT_KEY_CITY_NAME_ADRIANOPLE + TXT_KEY_CITY_NAME_NICAEA + TXT_KEY_CITY_NAME_ANTIOCH + TXT_KEY_CITY_NAME_NICOMEDIA + TXT_KEY_CITY_NAME_ANGORA + TXT_KEY_CITY_NAME_TREBIZOND + TXT_KEY_CITY_NAME_ICONIUM + TXT_KEY_CITY_NAME_LAODICEA + TXT_KEY_CITY_NAME_DORYLAEUM + TXT_KEY_CITY_NAME_AMORIUM + TXT_KEY_CITY_NAME_PHILIPPOPOLIS + TXT_KEY_CITY_NAME_MISTRA + TXT_KEY_CITY_NAME_DYRRACHIUM + TXT_KEY_CITY_NAME_EDESSA + TXT_KEY_CITY_NAME_HERACLEA + TXT_KEY_CITY_NAME_THEODOSIOPOLIS + TXT_KEY_CITY_NAME_ODESSOS + TXT_KEY_CITY_NAME_MESEMBRIA + TXT_KEY_CITY_NAME_SARDICA + TXT_KEY_CITY_NAME_RAGUSA + TXT_KEY_CITY_NAME_PHILIPPI + TXT_KEY_CITY_NAME_JUSTINIANOPOLIS + TXT_KEY_CITY_NAME_IOANNINA + TXT_KEY_CITY_NAME_CEPHALONIA + TXT_KEY_CITY_NAME_SELYMBRIA + TXT_KEY_CITY_NAME_CALLIPOLIS + TXT_KEY_CITY_NAME_CHANDAX + TXT_KEY_CITY_NAME_LEFKOSIA + TXT_KEY_CITY_NAME_FAMAGUSTA + TXT_KEY_CITY_NAME_BARI + TXT_KEY_CITY_NAME_OTRANTO + TXT_KEY_CITY_NAME_CHALCEDON + TXT_KEY_CITY_NAME_NEOCAESAREA + TXT_KEY_CITY_NAME_METILENE + TXT_KEY_CITY_NAME_SELEUCIA + TXT_KEY_CITY_NAME_SEBASTEA + TXT_KEY_CITY_NAME_MYRA + TXT_KEY_CITY_NAME_GANGRA + TXT_KEY_CITY_NAME_OCHRYD + TXT_KEY_CITY_NAME_BUTHROTUM + TXT_KEY_CITY_NAME_NAISSUS + TXT_KEY_CITY_NAME_CHERSON + + + + BUILDINGCLASS_THEATRE + BUILDING_BYZANTINE_HIPPODROME + + + + + UNITCLASS_KNIGHT + UNIT_BYZANTINE_CATAPHRACT + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_THE_WHEEL + 1 + + + TECH_MYSTICISM + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_JUSTINIAN + 1 + + + CIVILIZATION_GREECE + AS3D_BYZANTIUM_SELECT + AS3D_BYZANTIUM_ORDER + + + + CIVILIZATION_CARTHAGE + TXT_KEY_CIV_CARTHAGE_DESC + TXT_KEY_CIV_CARTHAGE_SHORT_DESC + TXT_KEY_CIV_CARTHAGE_ADJECTIVE + TXT_KEY_CIV_CARTHAGE_PEDIA + PLAYERCOLOR_ORANGE + ART_DEF_CIVILIZATION_CARTHAGE + ARTSTYLE_GRECO_ROMAN + UNIT_ARTSTYLE_GRECO_ROMAN + 1 + 1 + + TXT_KEY_CITY_NAME_CARTHAGE + TXT_KEY_CITY_NAME_UTICA + TXT_KEY_CITY_NAME_HADRUMETUM + TXT_KEY_CITY_NAME_HIPPO + TXT_KEY_CITY_NAME_KERKOUANE + TXT_KEY_CITY_NAME_LEPTIS + TXT_KEY_CITY_NAME_THAPSUS + TXT_KEY_CITY_NAME_SICCA + TXT_KEY_CITY_NAME_THAENAE + TXT_KEY_CITY_NAME_TACAPE + TXT_KEY_CITY_NAME_SABRATHA + TXT_KEY_CITY_NAME_OEA + TXT_KEY_CITY_NAME_MALACA + TXT_KEY_CITY_NAME_ABDERA + TXT_KEY_CITY_NAME_SEXI + TXT_KEY_CITY_NAME_BARIA + TXT_KEY_CITY_NAME_CARMONA + TXT_KEY_CITY_NAME_ONOBA + TXT_KEY_CITY_NAME_CARTHAGO_NOVO + TXT_KEY_CITY_NAME_IBROSSIM + TXT_KEY_CITY_NAME_SARIM_BATIM + TXT_KEY_CITY_NAME_TIPASA + TXT_KEY_CITY_NAME_IOL + TXT_KEY_CITY_NAME_SIGA + TXT_KEY_CITY_NAME_RUSADDIR + TXT_KEY_CITY_NAME_TINGIS + TXT_KEY_CITY_NAME_LIXUS + TXT_KEY_CITY_NAME_MOGADOR + TXT_KEY_CITY_NAME_ZIS + TXT_KEY_CITY_NAME_MOTYA + TXT_KEY_CITY_NAME_SOLUS + TXT_KEY_CITY_NAME_LILYBAEUM + TXT_KEY_CITY_NAME_KARALIS + TXT_KEY_CITY_NAME_NORA + TXT_KEY_CITY_NAME_BITHIA + TXT_KEY_CITY_NAME_SULCIS + TXT_KEY_CITY_NAME_THARROS + TXT_KEY_CITY_NAME_OLBIA + TXT_KEY_CITY_NAME_MELITA + TXT_KEY_CITY_NAME_KOSSYRA + TXT_KEY_CITY_NAME_ZAMA + + + + BUILDINGCLASS_HARBOR + BUILDING_CARTHAGE_COTHON + + + + + UNITCLASS_HORSE_ARCHER + UNIT_CARTHAGE_NUMIDIAN_CAVALRY + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_FISHING + 1 + + + TECH_MINING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_HANNIBAL + 1 + + + CIVILIZATION_SPAIN + AS3D_CARTHAGE_SELECT + AS3D_CARTHAGE_ORDER + + + + CIVILIZATION_CELT + TXT_KEY_CIV_CELT_DESC + TXT_KEY_CIV_CELT_SHORT_DESC + TXT_KEY_CIV_CELT_ADJECTIVE + TXT_KEY_CIV_CELT_PEDIA + PLAYERCOLOR_LIGHT_ORANGE + ART_DEF_CIVILIZATION_CELTS + ARTSTYLE_EUROPEAN + UNIT_ARTSTYLE_EUROPEAN + 1 + 1 + + TXT_KEY_CITY_NAME_BIBRACTE + TXT_KEY_CITY_NAME_VIENNE + TXT_KEY_CITY_NAME_TOLOSA + TXT_KEY_CITY_NAME_GERGOVIA + TXT_KEY_CITY_NAME_CAMULODUNUM + TXT_KEY_CITY_NAME_VERLAMION + TXT_KEY_CITY_NAME_DURNOVARIA + TXT_KEY_CITY_NAME_ISCA + TXT_KEY_CITY_NAME_DUROCORTORUM + TXT_KEY_CITY_NAME_BAGACUM + TXT_KEY_CITY_NAME_NEMETOCENNA + TXT_KEY_CITY_NAME_CALLEVA + TXT_KEY_CITY_NAME_VENTA + TXT_KEY_CITY_NAME_ISURIUM + TXT_KEY_CITY_NAME_RATAE + TXT_KEY_CITY_NAME_LUTETIA + TXT_KEY_CITY_NAME_ENTREMONT + TXT_KEY_CITY_NAME_BURDIGALA + TXT_KEY_CITY_NAME_NEMAUSUS + TXT_KEY_CITY_NAME_SAMAROBRIVA + TXT_KEY_CITY_NAME_BRIXIA + TXT_KEY_CITY_NAME_MEDIOLANUM + TXT_KEY_CITY_NAME_CREMONA + TXT_KEY_CITY_NAME_TAURASIA + TXT_KEY_CITY_NAME_SINIGAGLIA + TXT_KEY_CITY_NAME_NOVIOMAGUS + TXT_KEY_CITY_NAME_DUROVERNUM + TXT_KEY_CITY_NAME_LUGUVALIO + TXT_KEY_CITY_NAME_LINDINIS + TXT_KEY_CITY_NAME_OKILIS + TXT_KEY_CITY_NAME_NUMANTIA + TXT_KEY_CITY_NAME_TIERNES + TXT_KEY_CITY_NAME_BOTORRITA + TXT_KEY_CITY_NAME_MORIDUNUM + TXT_KEY_CITY_NAME_TARA + TXT_KEY_CITY_NAME_EBLANA + TXT_KEY_CITY_NAME_ALESIA + TXT_KEY_CITY_NAME_ANDEMATUNUM + TXT_KEY_CITY_NAME_UBIORUM + TXT_KEY_CITY_NAME_GENEVA + TXT_KEY_CITY_NAME_VINDOBONA + TXT_KEY_CITY_NAME_PISONIUM + TXT_KEY_CITY_NAME_ACQUINCUM + TXT_KEY_CITY_NAME_TYLIS + TXT_KEY_CITY_NAME_ANCYRA + + + + BUILDINGCLASS_WALLS + BUILDING_CELTIC_DUN + + + + + UNITCLASS_SWORDSMAN + UNIT_CELTIC_GALLIC_WARRIOR + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_HUNTING + 1 + + + TECH_MYSTICISM + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_BRENNUS + 1 + + + LEADER_BOUDICA + 1 + + + CIVILIZATION_ENGLAND + AS3D_CELTS_SELECT + AS3D_CELTS_ORDER + + + + CIVILIZATION_CHINA + TXT_KEY_CIV_CHINA_DESC + TXT_KEY_CIV_CHINA_SHORT_DESC + TXT_KEY_CIV_CHINA_ADJECTIVE + TXT_KEY_CIV_CHINA_PEDIA + PLAYERCOLOR_DARK_PINK + ART_DEF_CIVILIZATION_CHINA + ARTSTYLE_ASIAN + UNIT_ARTSTYLE_ASIAN + 1 + 1 + + TXT_KEY_CITY_NAME_BEIJING + TXT_KEY_CITY_NAME_SHANGHAI + TXT_KEY_CITY_NAME_GUANGZHOU + TXT_KEY_CITY_NAME_NANJING + TXT_KEY_CITY_NAME_XIAN + TXT_KEY_CITY_NAME_CHENGDU + TXT_KEY_CITY_NAME_HANGZHOU + TXT_KEY_CITY_NAME_TIANJIN + TXT_KEY_CITY_NAME_MACAU + TXT_KEY_CITY_NAME_SHANDONG + TXT_KEY_CITY_NAME_KAIFENG + TXT_KEY_CITY_NAME_NINGBO + TXT_KEY_CITY_NAME_BAODING + TXT_KEY_CITY_NAME_YANGZHOU + TXT_KEY_CITY_NAME_HAERBIN + TXT_KEY_CITY_NAME_CHONGQING + TXT_KEY_CITY_NAME_LOYANG + TXT_KEY_CITY_NAME_KUNMING + TXT_KEY_CITY_NAME_TAIPEI + TXT_KEY_CITY_NAME_SHENYANG + TXT_KEY_CITY_NAME_TAIYUAN + TXT_KEY_CITY_NAME_TAINAN + TXT_KEY_CITY_NAME_DALIAN + TXT_KEY_CITY_NAME_LIJIANG + TXT_KEY_CITY_NAME_WUXI + TXT_KEY_CITY_NAME_SUZHOU + TXT_KEY_CITY_NAME_MAOMING + TXT_KEY_CITY_NAME_SHAOGUAN + TXT_KEY_CITY_NAME_YANGJIANG + TXT_KEY_CITY_NAME_HEYUAN + TXT_KEY_CITY_NAME_LIAONING + TXT_KEY_CITY_NAME_HUBEI + TXT_KEY_CITY_NAME_GANSU + TXT_KEY_CITY_NAME_HUANGSHI + TXT_KEY_CITY_NAME_YICHANG + TXT_KEY_CITY_NAME_YINGTAN + TXT_KEY_CITY_NAME_XINYU + TXT_KEY_CITY_NAME_XINZHENG + TXT_KEY_CITY_NAME_HANDAN + TXT_KEY_CITY_NAME_DUNHUANG + TXT_KEY_CITY_NAME_GAOYU + TXT_KEY_CITY_NAME_NANTONG + TXT_KEY_CITY_NAME_WEIFANG + TXT_KEY_CITY_NAME_XIKANG + + + + BUILDINGCLASS_THEATRE + BUILDING_CHINESE_PAVILLION + + + + + UNITCLASS_CROSSBOWMAN + UNIT_CHINA_CHOKONU + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_AGRICULTURE + 1 + + + TECH_MINING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_QIN_SHI_HUANG + 1 + + + LEADER_CHINESE_LEADER + 1 + + + NONE + AS3D_CHINA_SELECT + AS3D_CHINA_ORDER + + + + CIVILIZATION_EGYPT + TXT_KEY_CIV_EGYPT_DESC + TXT_KEY_CIV_EGYPT_SHORT_DESC + TXT_KEY_CIV_EGYPT_ADJECTIVE + TXT_KEY_CIV_EGYPT_PEDIA + PLAYERCOLOR_YELLOW + ART_DEF_CIVILIZATION_EGYPT + ARTSTYLE_MIDDLE_EAST + UNIT_ARTSTYLE_MIDDLE_EAST + 1 + 1 + + TXT_KEY_CITY_NAME_THEBES + TXT_KEY_CITY_NAME_MEMPHIS + TXT_KEY_CITY_NAME_HELIOPOLIS + TXT_KEY_CITY_NAME_ELEPHANTINE + TXT_KEY_CITY_NAME_ALEXANDRIA + TXT_KEY_CITY_NAME_PIRAMESSES + TXT_KEY_CITY_NAME_GIZA + TXT_KEY_CITY_NAME_BYBLOS + TXT_KEY_CITY_NAME_AKHETATEN + TXT_KEY_CITY_NAME_HIERACONPOLIS + TXT_KEY_CITY_NAME_ABYDOS + TXT_KEY_CITY_NAME_ASYUT + TXT_KEY_CITY_NAME_AVARIS + TXT_KEY_CITY_NAME_LISHT + TXT_KEY_CITY_NAME_BUTO + TXT_KEY_CITY_NAME_EDFU + TXT_KEY_CITY_NAME_PITHOM + TXT_KEY_CITY_NAME_BUSIRIS + TXT_KEY_CITY_NAME_KAHUN + TXT_KEY_CITY_NAME_ATHRIBIS + TXT_KEY_CITY_NAME_MENDES + TXT_KEY_CITY_NAME_ELASHMUNEIN + TXT_KEY_CITY_NAME_TANIS + TXT_KEY_CITY_NAME_BUBASTIS + TXT_KEY_CITY_NAME_THIS + TXT_KEY_CITY_NAME_ORYX + TXT_KEY_CITY_NAME_SEBENNYTUS + TXT_KEY_CITY_NAME_AKHMIN + TXT_KEY_CITY_NAME_KARNAK + TXT_KEY_CITY_NAME_LUXOR + TXT_KEY_CITY_NAME_ELKAB + TXT_KEY_CITY_NAME_ARMANT + TXT_KEY_CITY_NAME_BALAT + TXT_KEY_CITY_NAME_ELLAHUN + TXT_KEY_CITY_NAME_GHURAB + TXT_KEY_CITY_NAME_HAWARA + TXT_KEY_CITY_NAME_DASHUR + TXT_KEY_CITY_NAME_RAQOTE + TXT_KEY_CITY_NAME_DAMANHUR + TXT_KEY_CITY_NAME_MERIMDE + TXT_KEY_CITY_NAME_ABUSIR + TXT_KEY_CITY_NAME_HERAKLEOPOLIS + TXT_KEY_CITY_NAME_AKORIS + TXT_KEY_CITY_NAME_BENIHASAN + TXT_KEY_CITY_NAME_TASA + TXT_KEY_CITY_NAME_BADARI + TXT_KEY_CITY_NAME_HERMOPOLIS + TXT_KEY_CITY_NAME_AMRAH + TXT_KEY_CITY_NAME_NEGADE + TXT_KEY_CITY_NAME_KOPTOS + TXT_KEY_CITY_NAME_HERMONTHIS + TXT_KEY_CITY_NAME_OMBOS + TXT_KEY_CITY_NAME_ANIBA + TXT_KEY_CITY_NAME_SOLEB + TXT_KEY_CITY_NAME_SEMNA + TXT_KEY_CITY_NAME_AMARA + + + + BUILDINGCLASS_OBELISK + BUILDING_EGYPTIAN_OBELISK + + + + + UNITCLASS_CHARIOT + UNIT_EGYPT_WARCHARIOT + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_THE_WHEEL + 1 + + + TECH_AGRICULTURE + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_HATSHEPSUT + 1 + + + LEADER_RAMESSES + 1 + + + NONE + AS3D_EGYPT_SELECT + AS3D_EGYPT_ORDER + + + + CIVILIZATION_ENGLAND + TXT_KEY_CIV_ENGLAND_DESC + TXT_KEY_CIV_ENGLAND_SHORT_DESC + TXT_KEY_CIV_ENGLAND_ADJECTIVE + TXT_KEY_CIV_ENGLAND_PEDIA + PLAYERCOLOR_WHITE + ART_DEF_CIVILIZATION_ENGLAND + ARTSTYLE_EUROPEAN + UNIT_ARTSTYLE_EUROPEAN + 1 + 1 + + TXT_KEY_CITY_NAME_LONDON + TXT_KEY_CITY_NAME_YORK + TXT_KEY_CITY_NAME_NOTTHINGHAM + TXT_KEY_CITY_NAME_HASTINGS + TXT_KEY_CITY_NAME_CANTERBURY + TXT_KEY_CITY_NAME_COVENTRY + TXT_KEY_CITY_NAME_WARWICK + TXT_KEY_CITY_NAME_NEWCASTLE + TXT_KEY_CITY_NAME_OXFORD + TXT_KEY_CITY_NAME_LIVERPOOL + TXT_KEY_CITY_NAME_DOVER + TXT_KEY_CITY_NAME_BRIGHTON + TXT_KEY_CITY_NAME_NORWICH + TXT_KEY_CITY_NAME_LEEDS + TXT_KEY_CITY_NAME_READING + TXT_KEY_CITY_NAME_BIRMINGHAM + TXT_KEY_CITY_NAME_RICHMOND + TXT_KEY_CITY_NAME_EXETER + TXT_KEY_CITY_NAME_CAMBRIDGE + TXT_KEY_CITY_NAME_GLOUCESTER + TXT_KEY_CITY_NAME_MANCHESTER + TXT_KEY_CITY_NAME_BRISTOL + TXT_KEY_CITY_NAME_LEICESTER + TXT_KEY_CITY_NAME_CARLISLE + TXT_KEY_CITY_NAME_IPSWICH + TXT_KEY_CITY_NAME_PORTSMOUTH + TXT_KEY_CITY_NAME_BERWICK + TXT_KEY_CITY_NAME_BATH + TXT_KEY_CITY_NAME_MUMBLES + TXT_KEY_CITY_NAME_SOUTHAMPTON + TXT_KEY_CITY_NAME_SHEFFIELD + TXT_KEY_CITY_NAME_SALISBURY + TXT_KEY_CITY_NAME_COLCHESTER + TXT_KEY_CITY_NAME_PLYMOUTH + TXT_KEY_CITY_NAME_LANCASTER + TXT_KEY_CITY_NAME_BLACKPOOL + TXT_KEY_CITY_NAME_WINCHESTER + TXT_KEY_CITY_NAME_HULL + + + + BUILDINGCLASS_BANK + BUILDING_ENGLISH_STOCK_EXCHANGE + + + + + UNITCLASS_RIFLEMAN + UNIT_ENGLISH_REDCOAT + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_FISHING + 1 + + + TECH_MINING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_ELIZABETH + 1 + + + LEADER_VICTORIA + 1 + + + LEADER_CHURCHILL + 1 + + + CIVILIZATION_AMERICA + AS3D_ENGLAND_SELECT + AS3D_ENGLAND_ORDER + + + + CIVILIZATION_ETHIOPIA + TXT_KEY_CIV_ETHIOPIA_DESC + TXT_KEY_CIV_ETHIOPIA_SHORT_DESC + TXT_KEY_CIV_ETHIOPIA_ADJECTIVE + TXT_KEY_CIV_ETHIOPIA_PEDIA + PLAYERCOLOR_MIDDLE_GREEN + ART_DEF_CIVILIZATION_ETHIOPIA + ARTSTYLE_MIDDLE_EAST + UNIT_ARTSTYLE_MIDDLE_EAST + 1 + 1 + + TXT_KEY_CITY_NAME_AKSUM + TXT_KEY_CITY_NAME_GONDAR + TXT_KEY_CITY_NAME_LALIBELA + TXT_KEY_CITY_NAME_ADDIS_ABABA + TXT_KEY_CITY_NAME_YEHA + TXT_KEY_CITY_NAME_DEBRE_BERHAN + TXT_KEY_CITY_NAME_ADULIS + TXT_KEY_CITY_NAME_QOHAITO + TXT_KEY_CITY_NAME_MATARA + TXT_KEY_CITY_NAME_HAWULTI + TXT_KEY_CITY_NAME_MASSAWA + TXT_KEY_CITY_NAME_ADWA + TXT_KEY_CITY_NAME_FASIL_GHEBBI + TXT_KEY_CITY_NAME_ZEILA + TXT_KEY_CITY_NAME_BERBERA + TXT_KEY_CITY_NAME_HARAR + TXT_KEY_CITY_NAME_KASKASE + TXT_KEY_CITY_NAME_ADDI_GALAMO + TXT_KEY_CITY_NAME_TOKONDA + TXT_KEY_CITY_NAME_KUBAR + TXT_KEY_CITY_NAME_TEGULAT + TXT_KEY_CITY_NAME_DEBRE_TABOR + TXT_KEY_CITY_NAME_MAGDALA + TXT_KEY_CITY_NAME_ANKOBER + TXT_KEY_CITY_NAME_ASMARA + TXT_KEY_CITY_NAME_DIRE_DAWA + TXT_KEY_CITY_NAME_ADAMA + TXT_KEY_CITY_NAME_JIMMA + TXT_KEY_CITY_NAME_MEKELE + TXT_KEY_CITY_NAME_TIYA + TXT_KEY_CITY_NAME_DEIRA + TXT_KEY_CITY_NAME_GABAZA + TXT_KEY_CITY_NAME_DAHLAK_KEBIR + TXT_KEY_CITY_NAME_MELAZO + TXT_KEY_CITY_NAME_FIKYA + TXT_KEY_CITY_NAME_SABEA + TXT_KEY_CITY_NAME_HAWILA_ASSARAW + TXT_KEY_CITY_NAME_WEQRO + + + + BUILDINGCLASS_OBELISK + BUILDING_ETHIOPIAN_STELE + + + + + UNITCLASS_MUSKETMAN + UNIT_ETHIOPIAN_OROMO_WARRIOR + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_HUNTING + 1 + + + TECH_MINING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_ZARA_YAQOB + 1 + + + NONE + AS3D_ETHIOPIA_SELECT + AS3D_ETHIOPIA_ORDER + + + + CIVILIZATION_FRANCE + TXT_KEY_CIV_FRANCE_DESC + TXT_KEY_CIV_FRANCE_SHORT_DESC + TXT_KEY_CIV_FRANCE_ADJECTIVE + TXT_KEY_CIV_FRANCE_PEDIA + PLAYERCOLOR_DARK_BLUE + ART_DEF_CIVILIZATION_FRANCE + ARTSTYLE_EUROPEAN + UNIT_ARTSTYLE_EUROPEAN + 1 + 1 + + TXT_KEY_CITY_NAME_PARIS + TXT_KEY_CITY_NAME_ORLEANS + TXT_KEY_CITY_NAME_LYONS + TXT_KEY_CITY_NAME_RHEIMS + TXT_KEY_CITY_NAME_TOURS + TXT_KEY_CITY_NAME_MARSEILLES + TXT_KEY_CITY_NAME_CHARTRES + TXT_KEY_CITY_NAME_AVIGNON + TXT_KEY_CITY_NAME_ROUEN + TXT_KEY_CITY_NAME_GRENOBLE + TXT_KEY_CITY_NAME_DJION + TXT_KEY_CITY_NAME_AMIENS + TXT_KEY_CITY_NAME_CHERBOURG + TXT_KEY_CITY_NAME_POITIERS + TXT_KEY_CITY_NAME_TOULOUSE + TXT_KEY_CITY_NAME_BAYONNE + TXT_KEY_CITY_NAME_STRASBOURG + TXT_KEY_CITY_NAME_BREST + TXT_KEY_CITY_NAME_BORDEAUX + TXT_KEY_CITY_NAME_RENNES + TXT_KEY_CITY_NAME_NICE + TXT_KEY_CITY_NAME_SAINT_ETIENNE + TXT_KEY_CITY_NAME_NANTES + TXT_KEY_CITY_NAME_REIMS + TXT_KEY_CITY_NAME_LE_MANS + TXT_KEY_CITY_NAME_MONTPELLIER + TXT_KEY_CITY_NAME_LIMOGES + TXT_KEY_CITY_NAME_NANCY + TXT_KEY_CITY_NAME_LILLE + TXT_KEY_CITY_NAME_CAEN + TXT_KEY_CITY_NAME_TOULON + TXT_KEY_CITY_NAME_NIMES + TXT_KEY_CITY_NAME_LE_HAVRE + TXT_KEY_CITY_NAME_LOURDES + TXT_KEY_CITY_NAME_CARCASSONNE + TXT_KEY_CITY_NAME_CANNES + TXT_KEY_CITY_NAME_AIX_EN_PROVINCE + TXT_KEY_CITY_NAME_LA_ROCHELLE + TXT_KEY_CITY_NAME_BOURGES + TXT_KEY_CITY_NAME_CALAIS + + + + BUILDINGCLASS_OBSERVATORY + BUILDING_FRENCH_SALON + + + + + UNITCLASS_MUSKETMAN + UNIT_FRENCH_MUSKETEER + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_THE_WHEEL + 1 + + + TECH_AGRICULTURE + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_LOUIS_XIV + 1 + + + LEADER_NAPOLEON + 1 + + + LEADER_DE_GAULLE + 1 + + + CIVILIZATION_AMERICA + AS3D_FRANCE_SELECT + AS3D_FRANCE_ORDER + + + + CIVILIZATION_GERMANY + TXT_KEY_CIV_GERMANY_DESC + TXT_KEY_CIV_GERMANY_SHORT_DESC + TXT_KEY_CIV_GERMANY_ADJECTIVE + TXT_KEY_CIV_GERMANY_PEDIA + PLAYERCOLOR_GRAY + ART_DEF_CIVILIZATION_GERMANY + ARTSTYLE_EUROPEAN + UNIT_ARTSTYLE_EUROPEAN + 1 + 1 + + TXT_KEY_CITY_NAME_BERLIN + TXT_KEY_CITY_NAME_HAMBURG + TXT_KEY_CITY_NAME_MUNICH + TXT_KEY_CITY_NAME_COLOGNE + TXT_KEY_CITY_NAME_FRANKFURT + TXT_KEY_CITY_NAME_ESSEN + TXT_KEY_CITY_NAME_DORTMUND + TXT_KEY_CITY_NAME_STUTTGART + TXT_KEY_CITY_NAME_DUSSELDORF + TXT_KEY_CITY_NAME_BREMEN + TXT_KEY_CITY_NAME_HANNOVER + TXT_KEY_CITY_NAME_DUISBURG + TXT_KEY_CITY_NAME_LEIPZIG + TXT_KEY_CITY_NAME_DRESDEN + TXT_KEY_CITY_NAME_BONN + TXT_KEY_CITY_NAME_BOCHUM + TXT_KEY_CITY_NAME_BIELEFELD + TXT_KEY_CITY_NAME_KARLSRUHE + TXT_KEY_CITY_NAME_GELSENKIRCHEN + TXT_KEY_CITY_NAME_WIESBADEN + TXT_KEY_CITY_NAME_MUNSTER + TXT_KEY_CITY_NAME_ROSTOCK + TXT_KEY_CITY_NAME_CHEMNITZ + TXT_KEY_CITY_NAME_BRAUNSCHWEIG + TXT_KEY_CITY_NAME_HALLE + TXT_KEY_CITY_NAME_MONCHENGLADBACH + TXT_KEY_CITY_NAME_KIEL + TXT_KEY_CITY_NAME_WUPPERTAL + TXT_KEY_CITY_NAME_FREIBURG + TXT_KEY_CITY_NAME_HAGEN + TXT_KEY_CITY_NAME_ERFURT + TXT_KEY_CITY_NAME_KASSEL + TXT_KEY_CITY_NAME_OBERHAUSEN + TXT_KEY_CITY_NAME_HAMM + TXT_KEY_CITY_NAME_SAARBRUCKEN + TXT_KEY_CITY_NAME_KREFELD + TXT_KEY_CITY_NAME_POTSDAM + TXT_KEY_CITY_NAME_SOLINGEN + TXT_KEY_CITY_NAME_OSNABRUCK + TXT_KEY_CITY_NAME_LUDWIGSHAFEN + TXT_KEY_CITY_NAME_LEVERKUSEN + TXT_KEY_CITY_NAME_OLDENBURG + TXT_KEY_CITY_NAME_NEUSS + TXT_KEY_CITY_NAME_MULHEIM + TXT_KEY_CITY_NAME_DARMSTADT + TXT_KEY_CITY_NAME_HERNE + TXT_KEY_CITY_NAME_WURZBURG + TXT_KEY_CITY_NAME_RECKLINGHAUSEN + TXT_KEY_CITY_NAME_GOTTINGEN + TXT_KEY_CITY_NAME_WOLFSBURG + TXT_KEY_CITY_NAME_KOBLENZ + TXT_KEY_CITY_NAME_HILDESHEIM + TXT_KEY_CITY_NAME_ERLANGEN + + + + BUILDINGCLASS_FACTORY + BUILDING_GERMAN_ASSEMBLY_PLANT + + + + + UNITCLASS_TANK + UNIT_GERMAN_PANZER + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_HUNTING + 1 + + + TECH_MINING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_FREDERICK + 1 + + + LEADER_BISMARCK + 1 + + + NONE + AS3D_GERMANY_SELECT + AS3D_GERMANY_ORDER + + + + CIVILIZATION_GREECE + TXT_KEY_CIV_GREECE_DESC + TXT_KEY_CIV_GREECE_SHORT_DESC + TXT_KEY_CIV_GREECE_ADJECTIVE + TXT_KEY_CIV_GREECE_PEDIA + PLAYERCOLOR_LIGHT_BLUE + ART_DEF_CIVILIZATION_GREECE + ARTSTYLE_GRECO_ROMAN + UNIT_ARTSTYLE_GRECO_ROMAN + 1 + 1 + + TXT_KEY_CITY_NAME_ATHENS + TXT_KEY_CITY_NAME_SPARTA + TXT_KEY_CITY_NAME_CORINTH + TXT_KEY_CITY_NAME_THEBES + TXT_KEY_CITY_NAME_ARGOS + TXT_KEY_CITY_NAME_KNOSSOS + TXT_KEY_CITY_NAME_MYCENAE + TXT_KEY_CITY_NAME_PHARSALOS + TXT_KEY_CITY_NAME_EPHESUS + TXT_KEY_CITY_NAME_HALICARNASSUS + TXT_KEY_CITY_NAME_RHODES + TXT_KEY_CITY_NAME_ERETRIA + TXT_KEY_CITY_NAME_PERGAMON + TXT_KEY_CITY_NAME_MILETOS + TXT_KEY_CITY_NAME_MEGARA + TXT_KEY_CITY_NAME_PHOCAEA + TXT_KEY_CITY_NAME_SICYON + TXT_KEY_CITY_NAME_TIRYNS + TXT_KEY_CITY_NAME_SAMOS + TXT_KEY_CITY_NAME_MYTILENE + TXT_KEY_CITY_NAME_CHIOS + TXT_KEY_CITY_NAME_PAROS + TXT_KEY_CITY_NAME_TEGEA + TXT_KEY_CITY_NAME_ELIS + TXT_KEY_CITY_NAME_SYRACUSE + TXT_KEY_CITY_NAME_HERAKLEIA + TXT_KEY_CITY_NAME_GORTYN + TXT_KEY_CITY_NAME_CHALKIS + TXT_KEY_CITY_NAME_PYLOS + TXT_KEY_CITY_NAME_PELLA + TXT_KEY_CITY_NAME_NAXOS + TXT_KEY_CITY_NAME_SICYON + TXT_KEY_CITY_NAME_SMYRNA + TXT_KEY_CITY_NAME_LARISSA + TXT_KEY_CITY_NAME_APOLLONIA + TXT_KEY_CITY_NAME_MESSENE + TXT_KEY_CITY_NAME_ORCHOMENOS + TXT_KEY_CITY_NAME_AMBRACIA + TXT_KEY_CITY_NAME_KOS + TXT_KEY_CITY_NAME_KNIDOS + TXT_KEY_CITY_NAME_AMPHIPOLIS + TXT_KEY_CITY_NAME_PATRAS + TXT_KEY_CITY_NAME_LAMIA + TXT_KEY_CITY_NAME_NAFPLION + TXT_KEY_CITY_NAME_APOLYTON + + + + BUILDINGCLASS_COLOSSEUM + BUILDING_GREEK_ODEON + + + + + UNITCLASS_AXEMAN + UNIT_GREEK_PHALANX + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_FISHING + 1 + + + TECH_HUNTING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_ALEXANDER + 1 + + + LEADER_PERICLES + 1 + + + CIVILIZATION_BYZANTIUM + AS3D_GREECE_SELECT + AS3D_GREECE_ORDER + + + + CIVILIZATION_HOLY_ROMAN + TXT_KEY_CIV_HOLY_ROMAN_DESC + TXT_KEY_CIV_HOLY_ROMAN_SHORT_DESC + TXT_KEY_CIV_HOLY_ROMAN_ADJECTIVE + TXT_KEY_CIV_HOLY_ROMAN_PEDIA + PLAYERCOLOR_DARK_LEMON + ART_DEF_CIVILIZATION_HOLY_ROMAN + ARTSTYLE_EUROPEAN + UNIT_ARTSTYLE_EUROPEAN + 1 + 1 + + TXT_KEY_CITY_NAME_AACHEN + TXT_KEY_CITY_NAME_PRAGUE + TXT_KEY_CITY_NAME_VIENNA + TXT_KEY_CITY_NAME_NUREMBERG + TXT_KEY_CITY_NAME_AUGSBURG + TXT_KEY_CITY_NAME_MAINZ + TXT_KEY_CITY_NAME_ULM + TXT_KEY_CITY_NAME_FLORENCE + TXT_KEY_CITY_NAME_PISA + TXT_KEY_CITY_NAME_LUXEMBURG + TXT_KEY_CITY_NAME_STRASSBURG + TXT_KEY_CITY_NAME_LUBECK + TXT_KEY_CITY_NAME_BRANDENBURG + TXT_KEY_CITY_NAME_HEIDELBERG + TXT_KEY_CITY_NAME_TRIER + TXT_KEY_CITY_NAME_REGENSBURG + TXT_KEY_CITY_NAME_MAGDEBURG + TXT_KEY_CITY_NAME_WORMS + TXT_KEY_CITY_NAME_CONSTANCE + TXT_KEY_CITY_NAME_BASLE + TXT_KEY_CITY_NAME_ZURICH + TXT_KEY_CITY_NAME_SALZBURG + TXT_KEY_CITY_NAME_INNSBRUCK + TXT_KEY_CITY_NAME_TRENT + TXT_KEY_CITY_NAME_GENOA + TXT_KEY_CITY_NAME_LUCCA + TXT_KEY_CITY_NAME_SIENNA + TXT_KEY_CITY_NAME_ARLES + TXT_KEY_CITY_NAME_BESANCON + TXT_KEY_CITY_NAME_METZ + TXT_KEY_CITY_NAME_WIRTEN + TXT_KEY_CITY_NAME_BRUSSELS + TXT_KEY_CITY_NAME_ANTWERP + TXT_KEY_CITY_NAME_LUTTICH + TXT_KEY_CITY_NAME_STETTIN + TXT_KEY_CITY_NAME_KOLBERG + TXT_KEY_CITY_NAME_BRESLAU + TXT_KEY_CITY_NAME_OLMUTZ + TXT_KEY_CITY_NAME_PILSEN + TXT_KEY_CITY_NAME_BAMBERG + TXT_KEY_CITY_NAME_MANNHEIM + TXT_KEY_CITY_NAME_GOSLAR + TXT_KEY_CITY_NAME_SPIRES + TXT_KEY_CITY_NAME_PADERBORN + TXT_KEY_CITY_NAME_PASSAU + TXT_KEY_CITY_NAME_HAGENAU + + + + BUILDINGCLASS_COURTHOUSE + BUILDING_HOLY_ROMAN_RATHAUS + + + + + UNITCLASS_PIKEMAN + UNIT_HOLY_ROMAN_LANDSKNECHT + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_MYSTICISM + 1 + + + TECH_HUNTING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_CHARLEMAGNE + 1 + + + CIVILIZATION_GERMANY + AS3D_HOLY_ROMAN_SELECT + AS3D_HOLY_ROMAN_ORDER + + + + CIVILIZATION_INCA + TXT_KEY_CIV_INCA_DESC + TXT_KEY_CIV_INCA_SHORT_DESC + TXT_KEY_CIV_INCA_ADJECTIVE + TXT_KEY_CIV_INCA_PEDIA + PLAYERCOLOR_DARK_YELLOW + ART_DEF_CIVILIZATION_INCA + ARTSTYLE_SOUTH_AMERICA + UNIT_ARTSTYLE_SOUTH_AMERICA + 1 + 1 + + TXT_KEY_CITY_NAME_CUZCO + TXT_KEY_CITY_NAME_TIWANAKU + TXT_KEY_CITY_NAME_MACHU + TXT_KEY_CITY_NAME_OLLANTAYTAMBO + TXT_KEY_CITY_NAME_CORIHUAYACHINA + TXT_KEY_CITY_NAME_HUAMANGA + TXT_KEY_CITY_NAME_VILCAS + TXT_KEY_CITY_NAME_VILCABAMBA + TXT_KEY_CITY_NAME_VITCOS + TXT_KEY_CITY_NAME_ANDAHUAYLAS + TXT_KEY_CITY_NAME_ICA + TXT_KEY_CITY_NAME_AREQUIPA + TXT_KEY_CITY_NAME_NASCA + TXT_KEY_CITY_NAME_ATICO + TXT_KEY_CITY_NAME_JULI + TXT_KEY_CITY_NAME_CHUITO + TXT_KEY_CITY_NAME_CHUQUIAPO + TXT_KEY_CITY_NAME_HUANUCOPAMPA + TXT_KEY_CITY_NAME_TAMBOCCOCHA + TXT_KEY_CITY_NAME_HUARAS + TXT_KEY_CITY_NAME_RIOBAMBA + TXT_KEY_CITY_NAME_CAXAMALCA + TXT_KEY_CITY_NAME_SAUSA + TXT_KEY_CITY_NAME_TAMBOCOLORADO + TXT_KEY_CITY_NAME_HUACA + TXT_KEY_CITY_NAME_TUMBES + TXT_KEY_CITY_NAME_CHAN_CHAN + TXT_KEY_CITY_NAME_SIPAN + TXT_KEY_CITY_NAME_PACHACAMAC + TXT_KEY_CITY_NAME_LLACTAPATA + TXT_KEY_CITY_NAME_PISAC + TXT_KEY_CITY_NAME_KUELAP + TXT_KEY_CITY_NAME_PAJATEN + TXT_KEY_CITY_NAME_CHUCUITO + + + + BUILDINGCLASS_GRANARY + BUILDING_INCAN_TERRACE + + + + + UNITCLASS_WARRIOR + UNIT_INCAN_QUECHUA + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_AGRICULTURE + 1 + + + TECH_MYSTICISM + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_HUAYNA_CAPAC + 1 + + + CIVILIZATION_AMERICA + AS3D_INCA_SELECT + AS3D_INCA_ORDER + + + + CIVILIZATION_INDIA + TXT_KEY_CIV_INDIA_DESC + TXT_KEY_CIV_INDIA_SHORT_DESC + TXT_KEY_CIV_INDIA_ADJECTIVE + TXT_KEY_CIV_INDIA_PEDIA + PLAYERCOLOR_PURPLE + ART_DEF_CIVILIZATION_INDIA + ARTSTYLE_ASIAN + UNIT_ARTSTYLE_MIDDLE_EAST + 1 + 1 + + TXT_KEY_CITY_NAME_DELHI + TXT_KEY_CITY_NAME_BOMBAY + TXT_KEY_CITY_NAME_VIJAYANAGARA + TXT_KEY_CITY_NAME_PATALIPUTRA + TXT_KEY_CITY_NAME_VARANASI + TXT_KEY_CITY_NAME_AGRA + TXT_KEY_CITY_NAME_CALCUTTA + TXT_KEY_CITY_NAME_LAHORE + TXT_KEY_CITY_NAME_MADRAS + TXT_KEY_CITY_NAME_BANGALORE + TXT_KEY_CITY_NAME_HYDERABAD + TXT_KEY_CITY_NAME_MADURAI + TXT_KEY_CITY_NAME_AHMEDABAD + TXT_KEY_CITY_NAME_KOLHAPUR + TXT_KEY_CITY_NAME_PRAYAGA + TXT_KEY_CITY_NAME_AYODHYA + TXT_KEY_CITY_NAME_INDRAPRASTHA + TXT_KEY_CITY_NAME_MATHURA + TXT_KEY_CITY_NAME_UJJAIN + TXT_KEY_CITY_NAME_TAXILA + TXT_KEY_CITY_NAME_GULBARGA + TXT_KEY_CITY_NAME_JAUNPUR + TXT_KEY_CITY_NAME_RAJAGRIHA + TXT_KEY_CITY_NAME_SRAVASTI + TXT_KEY_CITY_NAME_TIRUCHIRAPALLI + TXT_KEY_CITY_NAME_THANJAVUR + TXT_KEY_CITY_NAME_BODHGAYA + TXT_KEY_CITY_NAME_KUSHINAGAR + TXT_KEY_CITY_NAME_AMARAVATI + TXT_KEY_CITY_NAME_GAUR + TXT_KEY_CITY_NAME_GWALIOR + TXT_KEY_CITY_NAME_JAIPUR + TXT_KEY_CITY_NAME_KARACHI + TXT_KEY_CITY_NAME_DHAKA + TXT_KEY_CITY_NAME_LUCKNOW + TXT_KEY_CITY_NAME_JODHPUR + TXT_KEY_CITY_NAME_PUNE + TXT_KEY_CITY_NAME_BHOPAL + TXT_KEY_CITY_NAME_INDORE + TXT_KEY_CITY_NAME_KANPUR + TXT_KEY_CITY_NAME_NAGPUR + TXT_KEY_CITY_NAME_PESHAWAR + TXT_KEY_CITY_NAME_MULTAN + TXT_KEY_CITY_NAME_SURAT + TXT_KEY_CITY_NAME_COCHIN + TXT_KEY_CITY_NAME_CUTTACK + TXT_KEY_CITY_NAME_BHUBANESHWAR + TXT_KEY_CITY_NAME_TAMRALIPTA + TXT_KEY_CITY_NAME_CHITTAGONG + TXT_KEY_CITY_NAME_GUWAHATI + TXT_KEY_CITY_NAME_VIJAYAWADA + TXT_KEY_CITY_NAME_MYSORE + TXT_KEY_CITY_NAME_SRIRANGAPATNA + TXT_KEY_CITY_NAME_AMRITSAR + TXT_KEY_CITY_NAME_SRINAGAR + TXT_KEY_CITY_NAME_REWALSAR + TXT_KEY_CITY_NAME_VAISHALI + TXT_KEY_CITY_NAME_CAMBAY + TXT_KEY_CITY_NAME_ANHILWARA + TXT_KEY_CITY_NAME_PAHARPUR + TXT_KEY_CITY_NAME_MAHASTHANGARH + TXT_KEY_CITY_NAME_GANGAI_KONDA_CHOLAPURAM + TXT_KEY_CITY_NAME_KANCHI + TXT_KEY_CITY_NAME_NAGAPATTINAM + TXT_KEY_CITY_NAME_KAVERIPATTINAM + TXT_KEY_CITY_NAME_KALYANI + TXT_KEY_CITY_NAME_DHARWAD + TXT_KEY_CITY_NAME_SALEM + TXT_KEY_CITY_NAME_COIMBATORE + TXT_KEY_CITY_NAME_MASULIPATNAM + TXT_KEY_CITY_NAME_BIDAR + TXT_KEY_CITY_NAME_GOLCONDA + TXT_KEY_CITY_NAME_ELLICHPUR + TXT_KEY_CITY_NAME_WARANGAL + TXT_KEY_CITY_NAME_HALEBID + TXT_KEY_CITY_NAME_PRATISHTHANA + TXT_KEY_CITY_NAME_BIJAPUR + TXT_KEY_CITY_NAME_SOLAPUR + TXT_KEY_CITY_NAME_CALICUT + TXT_KEY_CITY_NAME_BHARUCH + TXT_KEY_CITY_NAME_MANGALORE + TXT_KEY_CITY_NAME_DHAR + TXT_KEY_CITY_NAME_AMBER + TXT_KEY_CITY_NAME_CHITTOR + TXT_KEY_CITY_NAME_VRINDAVAN + TXT_KEY_CITY_NAME_BADORA + TXT_KEY_CITY_NAME_KALPI + TXT_KEY_CITY_NAME_BELUR + TXT_KEY_CITY_NAME_NAINITAL + TXT_KEY_CITY_NAME_JABALPUR + TXT_KEY_CITY_NAME_RANCHI + TXT_KEY_CITY_NAME_RAIPUR + TXT_KEY_CITY_NAME_SONEPUR + TXT_KEY_CITY_NAME_BOGRA + TXT_KEY_CITY_NAME_DARJEELING + TXT_KEY_CITY_NAME_IMPHAL + TXT_KEY_CITY_NAME_CHANDIGARH + + + + BUILDINGCLASS_JAIL + BUILDING_INDIAN_MAUSOLEUM + + + + + UNITCLASS_WORKER + UNIT_INDIAN_FAST_WORKER + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_MYSTICISM + 1 + + + TECH_MINING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_ASOKA + 1 + + + LEADER_GANDHI + 1 + + + NONE + AS3D_INDIA_SELECT + AS3D_INDIA_ORDER + + + + CIVILIZATION_JAPAN + TXT_KEY_CIV_JAPAN_DESC + TXT_KEY_CIV_JAPAN_SHORT_DESC + TXT_KEY_CIV_JAPAN_ADJECTIVE + TXT_KEY_CIV_JAPAN_PEDIA + PLAYERCOLOR_RED + ART_DEF_CIVILIZATION_JAPAN + ARTSTYLE_ASIAN + UNIT_ARTSTYLE_ASIAN + 1 + 1 + + TXT_KEY_CITY_NAME_KYOTO + TXT_KEY_CITY_NAME_OSAKA + TXT_KEY_CITY_NAME_TOKYO + TXT_KEY_CITY_NAME_SATSUMA + TXT_KEY_CITY_NAME_KAGOSHIMA + TXT_KEY_CITY_NAME_NARA + TXT_KEY_CITY_NAME_NAGOYA + TXT_KEY_CITY_NAME_IZUMO + TXT_KEY_CITY_NAME_NAGASAKI + TXT_KEY_CITY_NAME_YOKOHAMA + TXT_KEY_CITY_NAME_SHIMONOSEKI + TXT_KEY_CITY_NAME_MATSUYAMA + TXT_KEY_CITY_NAME_SAPPORO + TXT_KEY_CITY_NAME_HAKODATE + TXT_KEY_CITY_NAME_ISE + TXT_KEY_CITY_NAME_TOYAMA + TXT_KEY_CITY_NAME_FUKUSHIMA + TXT_KEY_CITY_NAME_SUO + TXT_KEY_CITY_NAME_BIZEN + TXT_KEY_CITY_NAME_ECHIZEN + TXT_KEY_CITY_NAME_IZUMI + TXT_KEY_CITY_NAME_OMI + TXT_KEY_CITY_NAME_ECHIGO + TXT_KEY_CITY_NAME_KOZUKE + TXT_KEY_CITY_NAME_SADO + TXT_KEY_CITY_NAME_KOBE + TXT_KEY_CITY_NAME_NAGANO + TXT_KEY_CITY_NAME_HIROSHIMA + TXT_KEY_CITY_NAME_TAKAYAMA + TXT_KEY_CITY_NAME_AKITA + TXT_KEY_CITY_NAME_FUKUOKA + TXT_KEY_CITY_NAME_AOMORI + TXT_KEY_CITY_NAME_KAMAKURO + TXT_KEY_CITY_NAME_KOCHI + TXT_KEY_CITY_NAME_NAHA + + + + BUILDINGCLASS_COAL_PLANT + BUILDING_JAPANESE_SHALE_PLANT + + + + + UNITCLASS_MACEMAN + UNIT_JAPAN_SAMURAI + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_FISHING + 1 + + + TECH_THE_WHEEL + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_TOKUGAWA + 1 + + + CIVILIZATION_KOREA + AS3D_JAPAN_SELECT + AS3D_JAPAN_ORDER + + + + CIVILIZATION_KHMER + TXT_KEY_CIV_KHMER_DESC + TXT_KEY_CIV_KHMER_SHORT_DESC + TXT_KEY_CIV_KHMER_ADJECTIVE + TXT_KEY_CIV_KHMER_PEDIA + PLAYERCOLOR_MIDDLE_BLUE + ART_DEF_CIVILIZATION_KHMER + ARTSTYLE_ASIAN + UNIT_ARTSTYLE_ASIAN + 1 + 1 + + TXT_KEY_CITY_NAME_YASODHARAPURA + TXT_KEY_CITY_NAME_HARIHARALAYA + TXT_KEY_CITY_NAME_ANGKOR_THOM + TXT_KEY_CITY_NAME_ANGKOR_WAT + TXT_KEY_CITY_NAME_NAGARA_JAYASRI + TXT_KEY_CITY_NAME_RAJAVIHARA + TXT_KEY_CITY_NAME_ISVARAPURA + TXT_KEY_CITY_NAME_BANTEAY_KDEI + TXT_KEY_CITY_NAME_JAYENDRANAGARI + TXT_KEY_CITY_NAME_PRE_RUP + TXT_KEY_CITY_NAME_VIMAYAPURA + TXT_KEY_CITY_NAME_LINGAPURA + TXT_KEY_CITY_NAME_KRONG_CHAKTOMUK + TXT_KEY_CITY_NAME_CHOK_GARGYAR + TXT_KEY_CITY_NAME_MAHENDRAPARVATA + TXT_KEY_CITY_NAME_AMARENDRAPURA + TXT_KEY_CITY_NAME_INDRAPURA + TXT_KEY_CITY_NAME_LAVO + TXT_KEY_CITY_NAME_PREAH_VIHEAR + TXT_KEY_CITY_NAME_PHANOM_RUNG + TXT_KEY_CITY_NAME_PHIMAI + TXT_KEY_CITY_NAME_MUANG_TAM + TXT_KEY_CITY_NAME_BENG_MELEA + TXT_KEY_CITY_NAME_PRASAT_BAKAN + TXT_KEY_CITY_NAME_SINGHAPURA + TXT_KEY_CITY_NAME_CHALIENG + TXT_KEY_CITY_NAME_SUKHOTHAI + TXT_KEY_CITY_NAME_VIANGCHAN + TXT_KEY_CITY_NAME_BATTAMBANG + TXT_KEY_CITY_NAME_SURYAPARVATA + TXT_KEY_CITY_NAME_PREY_NOKOR + TXT_KEY_CITY_NAME_O_KEO + TXT_KEY_CITY_NAME_ANINDITAPURA + TXT_KEY_CITY_NAME_ISANAPURA + TXT_KEY_CITY_NAME_SHRESTAPURA + TXT_KEY_CITY_NAME_ANGKOR_BOREI + TXT_KEY_CITY_NAME_VYADHAPURA + TXT_KEY_CITY_NAME_BHAVAPURA + TXT_KEY_CITY_NAME_SAMBHUPURA + TXT_KEY_CITY_NAME_LOVEK + TXT_KEY_CITY_NAME_UDONG + + + + BUILDINGCLASS_AQUEDUCT + BUILDING_KHMER_BARAY + + + + + UNITCLASS_WAR_ELEPHANT + UNIT_KHMER_BALLISTA_ELEPHANT + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_HUNTING + 1 + + + TECH_MINING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_SURYAVARMAN + 1 + + + NONE + AS3D_KHMER_SELECT + AS3D_KHMER_ORDER + + + + CIVILIZATION_KOREA + TXT_KEY_CIV_KOREA_DESC + TXT_KEY_CIV_KOREA_SHORT_DESC + TXT_KEY_CIV_KOREA_ADJECTIVE + TXT_KEY_CIV_KOREA_PEDIA + PLAYERCOLOR_DARK_CYAN + ART_DEF_CIVILIZATION_KOREA + ARTSTYLE_ASIAN + UNIT_ARTSTYLE_ASIAN + 1 + 1 + + TXT_KEY_CITY_NAME_SEOUL + TXT_KEY_CITY_NAME_PYONGYANG + TXT_KEY_CITY_NAME_WONSAN + TXT_KEY_CITY_NAME_PUSAN + TXT_KEY_CITY_NAME_NAMPO + TXT_KEY_CITY_NAME_CHEJU + TXT_KEY_CITY_NAME_HYANGSAN + TXT_KEY_CITY_NAME_ULSAN + TXT_KEY_CITY_NAME_INCHON + TXT_KEY_CITY_NAME_PYONGSONG + TXT_KEY_CITY_NAME_TAEJON + TXT_KEY_CITY_NAME_PAEGAM + TXT_KEY_CITY_NAME_MANPO + TXT_KEY_CITY_NAME_KAESONG + TXT_KEY_CITY_NAME_CHONJU + TXT_KEY_CITY_NAME_SARIWON + TXT_KEY_CITY_NAME_SUWON + TXT_KEY_CITY_NAME_HAEJU + TXT_KEY_CITY_NAME_TAEGU + TXT_KEY_CITY_NAME_CHINJE + TXT_KEY_CITY_NAME_TOKCHON + TXT_KEY_CITY_NAME_CHONGFU + TXT_KEY_CITY_NAME_TAEGWON + TXT_KEY_CITY_NAME_SOKCHO + TXT_KEY_CITY_NAME_HAMHUNG + TXT_KEY_CITY_NAME_IRI + TXT_KEY_CITY_NAME_HUICHON + TXT_KEY_CITY_NAME_NAMWON + TXT_KEY_CITY_NAME_KUMGANG + TXT_KEY_CITY_NAME_OIJONGBU + + + + BUILDINGCLASS_UNIVERSITY + BUILDING_KOREAN_SEOWON + + + + + UNITCLASS_CATAPULT + UNIT_KOREAN_HWACHA + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_MINING + 1 + + + TECH_MYSTICISM + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_WANGKON + 1 + + + CIVILIZATION_JAPAN + AS3D_KOREA_SELECT + AS3D_KOREA_ORDER + + + + CIVILIZATION_MALI + TXT_KEY_CIV_MALI_DESC + TXT_KEY_CIV_MALI_SHORT_DESC + TXT_KEY_CIV_MALI_ADJECTIVE + TXT_KEY_CIV_MALI_PEDIA + PLAYERCOLOR_PEACH + ART_DEF_CIVILIZATION_MALI + ARTSTYLE_MIDDLE_EAST + UNIT_ARTSTYLE_MIDDLE_EAST + 1 + 1 + + TXT_KEY_CITY_NAME_TIMBUKTU + TXT_KEY_CITY_NAME_DJENNE + TXT_KEY_CITY_NAME_KUMBISALEH + TXT_KEY_CITY_NAME_GAO + TXT_KEY_CITY_NAME_WALATA + TXT_KEY_CITY_NAME_NIANI + TXT_KEY_CITY_NAME_AWDAGHOST + TXT_KEY_CITY_NAME_TADMEKKA + TXT_KEY_CITY_NAME_TEKEDDA + TXT_KEY_CITY_NAME_AWLIL + TXT_KEY_CITY_NAME_WADAN + TXT_KEY_CITY_NAME_AGADES + TXT_KEY_CITY_NAME_TEODENI + TXT_KEY_CITY_NAME_TAGHAZA + TXT_KEY_CITY_NAME_KATSINA + TXT_KEY_CITY_NAME_KANO + TXT_KEY_CITY_NAME_ZARIA + TXT_KEY_CITY_NAME_BILMA + TXT_KEY_CITY_NAME_NGAZARGUMU + TXT_KEY_CITY_NAME_KANGABA + TXT_KEY_CITY_NAME_DIA + TXT_KEY_CITY_NAME_TIRAQQA + TXT_KEY_CITY_NAME_AWKAR + TXT_KEY_CITY_NAME_KUKIYA + TXT_KEY_CITY_NAME_TAKRUR + TXT_KEY_CITY_NAME_ARAWAN + TXT_KEY_CITY_NAME_SYA + TXT_KEY_CITY_NAME_TAOUDENNI + TXT_KEY_CITY_NAME_BAMBOUK + TXT_KEY_CITY_NAME_KIRINA + + + + BUILDINGCLASS_FORGE + BUILDING_MALI_MINT + + + + + UNITCLASS_ARCHER + UNIT_MALI_SKIRMISHER + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_THE_WHEEL + 1 + + + TECH_MINING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_MANSA_MUSA + 1 + + + NONE + AS3D_MALI_SELECT + AS3D_MALI_ORDER + + + + CIVILIZATION_MAYA + TXT_KEY_CIV_MAYA_DESC + TXT_KEY_CIV_MAYA_SHORT_DESC + TXT_KEY_CIV_MAYA_ADJECTIVE + TXT_KEY_CIV_MAYA_PEDIA + PLAYERCOLOR_MIDDLE_CYAN + ART_DEF_CIVILIZATION_MAYA + ARTSTYLE_SOUTH_AMERICA + UNIT_ARTSTYLE_SOUTH_AMERICA + 1 + 1 + + TXT_KEY_CITY_NAME_MUTAL + TXT_KEY_CITY_NAME_LAKAMHA + TXT_KEY_CITY_NAME_CHICHEN_ITZA + TXT_KEY_CITY_NAME_UXMAL + TXT_KEY_CITY_NAME_MAYAPAN + TXT_KEY_CITY_NAME_CALAKMUL + TXT_KEY_CITY_NAME_OXHUITZA + TXT_KEY_CITY_NAME_XUKPI + TXT_KEY_CITY_NAME_QUIRIGUA + TXT_KEY_CITY_NAME_IZANCANAC + TXT_KEY_CITY_NAME_YOKIB + TXT_KEY_CITY_NAME_ALTUN_HA + TXT_KEY_CITY_NAME_IZAMAL + TXT_KEY_CITY_NAME_ZAMA + TXT_KEY_CITY_NAME_COBA + TXT_KEY_CITY_NAME_DZIBILCHALTUN + TXT_KEY_CITY_NAME_COZUMEL + TXT_KEY_CITY_NAME_EDZNA + TXT_KEY_CITY_NAME_OXKINTOK + TXT_KEY_CITY_NAME_BECAN + TXT_KEY_CITY_NAME_NAKBE + TXT_KEY_CITY_NAME_CIVAL + TXT_KEY_CITY_NAME_LAMANAIN + TXT_KEY_CITY_NAME_KAMINALJUYU + TXT_KEY_CITY_NAME_TAKALIK_ABAJ + TXT_KEY_CITY_NAME_HOLMUL + TXT_KEY_CITY_NAME_WAKA + TXT_KEY_CITY_NAME_LUBAANTUM + TXT_KEY_CITY_NAME_SIAAN_KAAN + TXT_KEY_CITY_NAME_BONAMPAK + TXT_KEY_CITY_NAME_TONINA + TXT_KEY_CITY_NAME_TAZUMAL + TXT_KEY_CITY_NAME_COMALCALCO + TXT_KEY_CITY_NAME_NIM_LI_PUNIT + TXT_KEY_CITY_NAME_EKBALAM + TXT_KEY_CITY_NAME_SAYIL + TXT_KEY_CITY_NAME_KABAH + TXT_KEY_CITY_NAME_LABNA + TXT_KEY_CITY_NAME_WAK_KABNAL + TXT_KEY_CITY_NAME_XUNANTUNICH + TXT_KEY_CITY_NAME_IZAPA + TXT_KEY_CITY_NAME_NOJ_PETEN + TXT_KEY_CITY_NAME_UTALTAN + TXT_KEY_CITY_NAME_MANI + + + + BUILDINGCLASS_COLOSSEUM + BUILDING_MAYA_BALL_COURT + + + + + UNITCLASS_SPEARMAN + UNIT_MAYA_HOLKAN + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_MINING + 1 + + + TECH_MYSTICISM + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_PACAL + 1 + + + CIVILIZATION_AMERICA + AS3D_MAYA_SELECT + AS3D_MAYA_ORDER + + + + CIVILIZATION_MONGOL + TXT_KEY_CIV_MONGOL_DESC + TXT_KEY_CIV_MONGOL_SHORT_DESC + TXT_KEY_CIV_MONGOL_ADJECTIVE + TXT_KEY_CIV_MONGOL_PEDIA + PLAYERCOLOR_BROWN + ART_DEF_CIVILIZATION_MONGOL + ARTSTYLE_ASIAN + UNIT_ARTSTYLE_ASIAN + 1 + 1 + + TXT_KEY_CITY_NAME_KARAKORUM + TXT_KEY_CITY_NAME_BESHBALIK + TXT_KEY_CITY_NAME_TURFAN + TXT_KEY_CITY_NAME_HSIA + TXT_KEY_CITY_NAME_OLDSARAI + TXT_KEY_CITY_NAME_NEWSARAI + TXT_KEY_CITY_NAME_SAMARQAND + TXT_KEY_CITY_NAME_TABRIZ + TXT_KEY_CITY_NAME_TIFLIS + TXT_KEY_CITY_NAME_OTRAR + TXT_KEY_CITY_NAME_SANCHU + TXT_KEY_CITY_NAME_KAZAN + TXT_KEY_CITY_NAME_ALMARIKH + TXT_KEY_CITY_NAME_ULAANBAATAR + TXT_KEY_CITY_NAME_HOVD + TXT_KEY_CITY_NAME_DARHAN + TXT_KEY_CITY_NAME_DALANDZADGAD + TXT_KEY_CITY_NAME_MANDALGOVI + TXT_KEY_CITY_NAME_CHOYBALSAN + TXT_KEY_CITY_NAME_ERDENET + TXT_KEY_CITY_NAME_TSETSERLEG + TXT_KEY_CITY_NAME_BARUUNURT + TXT_KEY_CITY_NAME_EREEN + TXT_KEY_CITY_NAME_BATSHIREET + TXT_KEY_CITY_NAME_CHOYR + TXT_KEY_CITY_NAME_ULAANGOM + TXT_KEY_CITY_NAME_TOSONTSENGEL + TXT_KEY_CITY_NAME_ATLAY + TXT_KEY_CITY_NAME_ULIASTAY + TXT_KEY_CITY_NAME_BAYANHONGOR + TXT_KEY_CITY_NAME_HARAYRAG + TXT_KEY_CITY_NAME_NALAYH + TXT_KEY_CITY_NAME_TES + + + + BUILDINGCLASS_STABLE + BUILDING_MONGOL_GER + + + + + UNITCLASS_HORSE_ARCHER + UNIT_MONGOL_KESHIK + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_THE_WHEEL + 1 + + + TECH_HUNTING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_GENGHIS_KHAN + 1 + + + LEADER_KUBLAI_KHAN + 1 + + + CIVILIZATION_CHINA + AS3D_MONGOL_SELECT + AS3D_MONGOL_ORDER + + + + CIVILIZATION_NATIVE_AMERICA + TXT_KEY_CIV_NATIVE_AMERICA_DESC + TXT_KEY_CIV_NATIVE_AMERICA_SHORT_DESC + TXT_KEY_CIV_NATIVE_AMERICA_ADJECTIVE + TXT_KEY_CIV_NATIVE_AMERICA_PEDIA + PLAYERCOLOR_LIGHT_BROWN + ART_DEF_CIVILIZATION_NATIVE_AMERICA + ARTSTYLE_SOUTH_AMERICA + UNIT_ARTSTYLE_SOUTH_AMERICA + 1 + 1 + + TXT_KEY_CITY_NAME_CAHOKIA + TXT_KEY_CITY_NAME_POVERTY_POINT + TXT_KEY_CITY_NAME_MOUND_CITY + TXT_KEY_CITY_NAME_CHACO_CANYON + TXT_KEY_CITY_NAME_MESA_VERDE + TXT_KEY_CITY_NAME_SNAKETOWN + TXT_KEY_CITY_NAME_SPIRO + TXT_KEY_CITY_NAME_MOUNDVILLE + TXT_KEY_CITY_NAME_NACOGDOCHES + TXT_KEY_CITY_NAME_NANIH_WAIYA + TXT_KEY_CITY_NAME_ANHAICA + TXT_KEY_CITY_NAME_ETOWAH + TXT_KEY_CITY_NAME_OCMULGEE + TXT_KEY_CITY_NAME_KITUHWA + TXT_KEY_CITY_NAME_FORT_ANCIENT + TXT_KEY_CITY_NAME_ONONDAGA + TXT_KEY_CITY_NAME_BAWATING + TXT_KEY_CITY_NAME_ACOMA + TXT_KEY_CITY_NAME_NAMBE + TXT_KEY_CITY_NAME_HOVENSWEEP + TXT_KEY_CITY_NAME_CASA_GRANDE + TXT_KEY_CITY_NAME_CRIEL + TXT_KEY_CITY_NAME_JOARA + TXT_KEY_CITY_NAME_LAKE_JACKSON + TXT_KEY_CITY_NAME_CHOTA + TXT_KEY_CITY_NAME_ONEIDA + TXT_KEY_CITY_NAME_LOGSTOWN + TXT_KEY_CITY_NAME_FIVE_FINGER_RIDGE + TXT_KEY_CITY_NAME_FRIJOLES_CANYON + TXT_KEY_CITY_NAME_PUYE_CLIFF + TXT_KEY_CITY_NAME_KIET_SIEL + TXT_KEY_CITY_NAME_MONTEZUMA_CASTLE + TXT_KEY_CITY_NAME_WICKLIFFE + TXT_KEY_CITY_NAME_AZTALAN + TXT_KEY_CITY_NAME_ANGEL_MOUNDS + TXT_KEY_CITY_NAME_TSIREGE + TXT_KEY_CITY_NAME_TAOS + TXT_KEY_CITY_NAME_ZUNI + TXT_KEY_CITY_NAME_TISHOMINGO + TXT_KEY_CITY_NAME_SHAUGAWAUMIKONG + TXT_KEY_CITY_NAME_ALLUMETTE + TXT_KEY_CITY_NAME_WENDAKE + TXT_KEY_CITY_NAME_NORRIDGEWOCK + TXT_KEY_CITY_NAME_MUTSUN + TXT_KEY_CITY_NAME_OZETTE + TXT_KEY_CITY_NAME_ESTIPAH_SKIKIKINI_KOTS + TXT_KEY_CITY_NAME_HUECO_TANKS + TXT_KEY_CITY_NAME_UKPIAGVIK + TXT_KEY_CITY_NAME_KETCHIKAN + TXT_KEY_CITY_NAME_KUUJJUAQ + + + + BUILDINGCLASS_OBELISK + BUILDING_NATIVE_AMERICA_TOTEM + + + + + UNITCLASS_AXEMAN + UNIT_NATIVE_AMERICA_DOG_SOLDIER + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_AGRICULTURE + 1 + + + TECH_FISHING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_SITTING_BULL + 1 + + + CIVILIZATION_AMERICA + AS3D_NATIVE_AMERICA_SELECT + AS3D_NATIVE_AMERICA_ORDER + + + + CIVILIZATION_NETHERLANDS + TXT_KEY_CIV_NETHERLANDS_DESC + TXT_KEY_CIV_NETHERLANDS_SHORT_DESC + TXT_KEY_CIV_NETHERLANDS_ADJECTIVE + TXT_KEY_CIV_NETHERLANDS_PEDIA + PLAYERCOLOR_DARK_ORANGE + ART_DEF_CIVILIZATION_NETHERLANDS + ARTSTYLE_EUROPEAN + UNIT_ARTSTYLE_EUROPEAN + 1 + 1 + + TXT_KEY_CITY_NAME_AMSTERDAM + TXT_KEY_CITY_NAME_UTRECHT + TXT_KEY_CITY_NAME_S_GRAVENHAGE + TXT_KEY_CITY_NAME_ROTTERDAM + TXT_KEY_CITY_NAME_NIJMEGEN + TXT_KEY_CITY_NAME_MAASTRICHT + TXT_KEY_CITY_NAME_MIDDELBURG + TXT_KEY_CITY_NAME_DELFT + TXT_KEY_CITY_NAME_LEIDEN + TXT_KEY_CITY_NAME_HAARLEM + TXT_KEY_CITY_NAME_S_HERTOGENBOSCH + TXT_KEY_CITY_NAME_DORESTAD + TXT_KEY_CITY_NAME_DEVENTER + TXT_KEY_CITY_NAME_KAMPEN + TXT_KEY_CITY_NAME_GRONINGEN + TXT_KEY_CITY_NAME_LEEUWARDEN + TXT_KEY_CITY_NAME_ENKHUIZEN + TXT_KEY_CITY_NAME_HOORN + TXT_KEY_CITY_NAME_TIEL + TXT_KEY_CITY_NAME_BREDA + TXT_KEY_CITY_NAME_EINDHOVEN + TXT_KEY_CITY_NAME_DORDRECHT + TXT_KEY_CITY_NAME_VLISSINGEN + TXT_KEY_CITY_NAME_KAMPVERE + TXT_KEY_CITY_NAME_ROERMOND + TXT_KEY_CITY_NAME_ZUTPHEN + TXT_KEY_CITY_NAME_ARNHEM + TXT_KEY_CITY_NAME_AMERSFOORT + TXT_KEY_CITY_NAME_GOUDA + TXT_KEY_CITY_NAME_ALKMAAR + TXT_KEY_CITY_NAME_MEDEMBLIK + TXT_KEY_CITY_NAME_GORKUM + TXT_KEY_CITY_NAME_TILBURG + TXT_KEY_CITY_NAME_BERGEN_OP_ZOOM + TXT_KEY_CITY_NAME_ZWOLLE + TXT_KEY_CITY_NAME_HARDERWIJK + TXT_KEY_CITY_NAME_VENLO + TXT_KEY_CITY_NAME_FRANEKER + TXT_KEY_CITY_NAME_HARLINGEN + TXT_KEY_CITY_NAME_STAVOREN + TXT_KEY_CITY_NAME_ASSEN + TXT_KEY_CITY_NAME_ENSCHEDE + TXT_KEY_CITY_NAME_APELDOORN + TXT_KEY_CITY_NAME_LELYSTAD + TXT_KEY_CITY_NAME_ALMERE + + + + BUILDINGCLASS_LEVEE + BUILDING_NETHERLANDS_DIKE + + + + + UNITCLASS_GALLEON + UNIT_NETHERLANDS_OOSTINDIEVAARDER + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_AGRICULTURE + 1 + + + TECH_FISHING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_WILLEM_VAN_ORANJE + 1 + + + CIVILIZATION_AMERICA + AS3D_NETHERLANDS_SELECT + AS3D_NETHERLANDS_ORDER + + + + CIVILIZATION_OTTOMAN + TXT_KEY_CIV_OTTOMAN_DESC + TXT_KEY_CIV_OTTOMAN_SHORT_DESC + TXT_KEY_CIV_OTTOMAN_ADJECTIVE + TXT_KEY_CHANGED_CIV_OTTOMAN_PEDIA + PLAYERCOLOR_DARK_GREEN + ART_DEF_CIVILIZATION_OTTOMANS + ARTSTYLE_MIDDLE_EAST + UNIT_ARTSTYLE_MIDDLE_EAST + 1 + 1 + + TXT_KEY_CITY_NAME_ISTANBUL + TXT_KEY_CITY_NAME_EDIRNE + TXT_KEY_CITY_NAME_ANKARA + TXT_KEY_CITY_NAME_BURSA + TXT_KEY_CITY_NAME_KONYA + TXT_KEY_CITY_NAME_SAMSUN + TXT_KEY_CITY_NAME_GAZIANTEP + TXT_KEY_CITY_NAME_DIYARBAKIR + TXT_KEY_CITY_NAME_IZMIR + TXT_KEY_CITY_NAME_KAYSERI + TXT_KEY_CITY_NAME_MALATYA + TXT_KEY_CITY_NAME_MARSIN + TXT_KEY_CITY_NAME_ANTALYA + TXT_KEY_CITY_NAME_ZONGULDAK + TXT_KEY_CITY_NAME_DENIZLI + TXT_KEY_CITY_NAME_OIDU + TXT_KEY_CITY_NAME_MUGLA + TXT_KEY_CITY_NAME_ESKISEHIR + TXT_KEY_CITY_NAME_INEBOLU + TXT_KEY_CITY_NAME_SINOP + TXT_KEY_CITY_NAME_ADANA + TXT_KEY_CITY_NAME_TARSUS + TXT_KEY_CITY_NAME_ARTUIN + TXT_KEY_CITY_NAME_BODRUM + TXT_KEY_CITY_NAME_EREGLI + TXT_KEY_CITY_NAME_SILIFKE + TXT_KEY_CITY_NAME_SIVAS + TXT_KEY_CITY_NAME_AMASYA + TXT_KEY_CITY_NAME_MARMARIS + TXT_KEY_CITY_NAME_TRABZON + TXT_KEY_CITY_NAME_ERZURUM + TXT_KEY_CITY_NAME_URFA + TXT_KEY_CITY_NAME_IZMIT + TXT_KEY_CITY_NAME_AFYON + TXT_KEY_CITY_NAME_BITLIS + TXT_KEY_CITY_NAME_MARMARIS + + + + BUILDINGCLASS_AQUEDUCT + BUILDING_OTTOMAN_HAMMAM + + + + + UNITCLASS_MUSKETMAN + UNIT_OTTOMAN_JANISSARY + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_THE_WHEEL + 1 + + + TECH_AGRICULTURE + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_MEHMED + 1 + + + LEADER_SULEIMAN + 1 + + + NONE + AS3D_OTTOMAN_SELECT + AS3D_OTTOMAN_ORDER + + + + CIVILIZATION_PERSIA + TXT_KEY_CIV_PERSIA_DESC + TXT_KEY_CIV_PERSIA_SHORT_DESC + TXT_KEY_CIV_PERSIA_ADJECTIVE + TXT_KEY_CIV_PERSIA_PEDIA + PLAYERCOLOR_CYAN + ART_DEF_CIVILIZATION_PERSIA + ARTSTYLE_MIDDLE_EAST + UNIT_ARTSTYLE_MIDDLE_EAST + 1 + 1 + + TXT_KEY_CITY_NAME_PERSEPOLIS + TXT_KEY_CITY_NAME_PASARGADAE + TXT_KEY_CITY_NAME_SUSA + TXT_KEY_CITY_NAME_ECBATANA + TXT_KEY_CITY_NAME_TARSUS + TXT_KEY_CITY_NAME_GORDIUM + TXT_KEY_CITY_NAME_BACTRA + TXT_KEY_CITY_NAME_SARDIS + TXT_KEY_CITY_NAME_ERGILI + TXT_KEY_CITY_NAME_DARIUSHKABIR + TXT_KEY_CITY_NAME_GHULAMAN + TXT_KEY_CITY_NAME_ZOHAK + TXT_KEY_CITY_NAME_ISTAKHR + TXT_KEY_CITY_NAME_JINJAN + TXT_KEY_CITY_NAME_BORAZJAN + TXT_KEY_CITY_NAME_HERAT + TXT_KEY_CITY_NAME_DAKYANUS + TXT_KEY_CITY_NAME_BAMPUR + TXT_KEY_CITY_NAME_TURENGTEPE + TXT_KEY_CITY_NAME_REY + TXT_KEY_CITY_NAME_SHIRAZ + TXT_KEY_CITY_NAME_TUSHPA + TXT_KEY_CITY_NAME_HASANLU + TXT_KEY_CITY_NAME_GABAE + TXT_KEY_CITY_NAME_MERV + TXT_KEY_CITY_NAME_BEHISTUN + TXT_KEY_CITY_NAME_KANDAHAR + TXT_KEY_CITY_NAME_ALTINTEPE + TXT_KEY_CITY_NAME_BUNYAN + TXT_KEY_CITY_NAME_CHARSADDA + TXT_KEY_CITY_NAME_URATYUBE + TXT_KEY_CITY_NAME_DURAEUROPOS + TXT_KEY_CITY_NAME_ALEPPO + TXT_KEY_CITY_NAME_QATNA + TXT_KEY_CITY_NAME_KABUL + TXT_KEY_CITY_NAME_CAPISA + TXT_KEY_CITY_NAME_KYRESKHATA + TXT_KEY_CITY_NAME_MARAKANDA + TXT_KEY_CITY_NAME_PESHAWAR + TXT_KEY_CITY_NAME_VAN + TXT_KEY_CITY_NAME_PTEIRA + TXT_KEY_CITY_NAME_ARSHADA + TXT_KEY_CITY_NAME_ARTAKOANA + TXT_KEY_CITY_NAME_ASPABOTA + TXT_KEY_CITY_NAME_AUTIYARA + TXT_KEY_CITY_NAME_BAGASTANA + TXT_KEY_CITY_NAME_BAXTRI + TXT_KEY_CITY_NAME_DARMASA + TXT_KEY_CITY_NAME_DAPHNAI + TXT_KEY_CITY_NAME_DRAPSAKA + TXT_KEY_CITY_NAME_EION + TXT_KEY_CITY_NAME_GANDUTAVA + TXT_KEY_CITY_NAME_GAUGAMELA + TXT_KEY_CITY_NAME_HARMOZEIA + TXT_KEY_CITY_NAME_EKATOMPYLOS + TXT_KEY_CITY_NAME_IZATA + TXT_KEY_CITY_NAME_KAMPADA + TXT_KEY_CITY_NAME_KAPISA + TXT_KEY_CITY_NAME_KARMANA + TXT_KEY_CITY_NAME_KOUNAXA + TXT_KEY_CITY_NAME_KUGANAKA + TXT_KEY_CITY_NAME_NAUTAKA + TXT_KEY_CITY_NAME_PAISHIYAUVADA + TXT_KEY_CITY_NAME_PATIGRBANA + TXT_KEY_CITY_NAME_PHRADA + + + + BUILDINGCLASS_GROCER + BUILDING_PERSIAN_APOTHECARY + + + + + UNITCLASS_CHARIOT + UNIT_PERSIA_IMMORTAL + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_AGRICULTURE + 1 + + + TECH_HUNTING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_CYRUS + 1 + + + LEADER_DARIUS + 1 + + + CIVILIZATION_ARABIA + AS3D_PERSIA_SELECT + AS3D_PERSIA_ORDER + + + + CIVILIZATION_PORTUGAL + TXT_KEY_CIV_PORTUGAL_DESC + TXT_KEY_CIV_PORTUGAL_SHORT_DESC + TXT_KEY_CIV_PORTUGAL_ADJECTIVE + TXT_KEY_CIV_PORTUGAL_PEDIA + PLAYERCOLOR_DARK_DARK_GREEN + ART_DEF_CIVILIZATION_PORTUGAL + ARTSTYLE_EUROPEAN + UNIT_ARTSTYLE_EUROPEAN + 1 + 1 + + TXT_KEY_CITY_NAME_LISBON + TXT_KEY_CITY_NAME_OPORTO + TXT_KEY_CITY_NAME_GUIMARAES + TXT_KEY_CITY_NAME_COIMBRA + TXT_KEY_CITY_NAME_EVORA + TXT_KEY_CITY_NAME_LAGOS + TXT_KEY_CITY_NAME_BRAGA + TXT_KEY_CITY_NAME_LEIRIA + TXT_KEY_CITY_NAME_FARO + TXT_KEY_CITY_NAME_SANTAREM + TXT_KEY_CITY_NAME_BRAGANZA + TXT_KEY_CITY_NAME_SAGRES + TXT_KEY_CITY_NAME_AVEIRO + TXT_KEY_CITY_NAME_VISEU + TXT_KEY_CITY_NAME_TOMAR + TXT_KEY_CITY_NAME_CINTRA + TXT_KEY_CITY_NAME_PORTALEGRE + TXT_KEY_CITY_NAME_ABRANTES + TXT_KEY_CITY_NAME_GUARDA + TXT_KEY_CITY_NAME_CHAVES + TXT_KEY_CITY_NAME_ELVAS + TXT_KEY_CITY_NAME_COVILHA + TXT_KEY_CITY_NAME_SILVES + TXT_KEY_CITY_NAME_VILA_REAL + TXT_KEY_CITY_NAME_TAVIRA + TXT_KEY_CITY_NAME_LEIXOES + TXT_KEY_CITY_NAME_SETUBAL + TXT_KEY_CITY_NAME_BEJA + TXT_KEY_CITY_NAME_SOURE + TXT_KEY_CITY_NAME_LAMEGO + TXT_KEY_CITY_NAME_PALMELA + TXT_KEY_CITY_NAME_SERPA + TXT_KEY_CITY_NAME_SINES + TXT_KEY_CITY_NAME_ALMADA + TXT_KEY_CITY_NAME_ESTREMOZ + TXT_KEY_CITY_NAME_ALCACER_DO_SAL + TXT_KEY_CITY_NAME_MERTOLA + TXT_KEY_CITY_NAME_MIRANDA_DO_DOURO + TXT_KEY_CITY_NAME_ANGRA_DO_HEROISMO + TXT_KEY_CITY_NAME_BAHIA + TXT_KEY_CITY_NAME_RIO_DE_JANEIRO + TXT_KEY_CITY_NAME_SAO_PAOLO + TXT_KEY_CITY_NAME_LUANDA + TXT_KEY_CITY_NAME_GOA + TXT_KEY_CITY_NAME_MACAO + + + + BUILDINGCLASS_CUSTOM_HOUSE + BUILDING_PORTUGAL_FEITORIA + + + + + UNITCLASS_CARAVEL + UNIT_PORTUGAL_CARRACK + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_FISHING + 1 + + + TECH_MINING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_JOAO + 1 + + + CIVILIZATION_AMERICA + AS3D_PORTUGAL_SELECT + AS3D_PORTUGAL_ORDER + + + + CIVILIZATION_ROME + TXT_KEY_CIV_ROME_DESC + TXT_KEY_CIV_ROME_SHORT_DESC + TXT_KEY_CIV_ROME_ADJECTIVE + TXT_KEY_CIV_ROME_PEDIA + PLAYERCOLOR_DARK_PURPLE + ART_DEF_CIVILIZATION_ROME + ARTSTYLE_GRECO_ROMAN + UNIT_ARTSTYLE_GRECO_ROMAN + 1 + 1 + + TXT_KEY_CITY_NAME_ROME + TXT_KEY_CITY_NAME_ANTIUM + TXT_KEY_CITY_NAME_CUMAE + TXT_KEY_CITY_NAME_NEAPOLIS + TXT_KEY_CITY_NAME_RAVENNA + TXT_KEY_CITY_NAME_ARRETIUM + TXT_KEY_CITY_NAME_MEDIOLANUM + TXT_KEY_CITY_NAME_ARPINUM + TXT_KEY_CITY_NAME_CIRCEI + TXT_KEY_CITY_NAME_SETIA + TXT_KEY_CITY_NAME_SATRICUM + TXT_KEY_CITY_NAME_ARDEA + TXT_KEY_CITY_NAME_OSTIA + TXT_KEY_CITY_NAME_VELITRAE + TXT_KEY_CITY_NAME_VIROCONIUM + TXT_KEY_CITY_NAME_TARENTUM + TXT_KEY_CITY_NAME_BRUNDISIUM + TXT_KEY_CITY_NAME_CAESARAUGUSTA + TXT_KEY_CITY_NAME_CAESAREA + TXT_KEY_CITY_NAME_PALMYRA + TXT_KEY_CITY_NAME_SIGNIA + TXT_KEY_CITY_NAME_AQUILEIA + TXT_KEY_CITY_NAME_CLUSIUM + TXT_KEY_CITY_NAME_SUTRIUM + TXT_KEY_CITY_NAME_CREMONA + TXT_KEY_CITY_NAME_PLACENTIA + TXT_KEY_CITY_NAME_HISPALIS + TXT_KEY_CITY_NAME_ARTAXATA + TXT_KEY_CITY_NAME_AURELIANORUM + TXT_KEY_CITY_NAME_NICOPOLIS + TXT_KEY_CITY_NAME_LONDINIUM + TXT_KEY_CITY_NAME_EBURACUM + TXT_KEY_CITY_NAME_GORDION + TXT_KEY_CITY_NAME_AGRIPPINA + TXT_KEY_CITY_NAME_LUGDUNUM + TXT_KEY_CITY_NAME_VERONA + TXT_KEY_CITY_NAME_CORFINIUM + TXT_KEY_CITY_NAME_TREVERI + TXT_KEY_CITY_NAME_SIRMIUM + TXT_KEY_CITY_NAME_AUGUSTADORUM + TXT_KEY_CITY_NAME_BAGACUM + TXT_KEY_CITY_NAME_LAURIACUM + TXT_KEY_CITY_NAME_TEURNIA + TXT_KEY_CITY_NAME_CURIA + TXT_KEY_CITY_NAME_FREGELLAE + TXT_KEY_CITY_NAME_ALBAFUCENS + TXT_KEY_CITY_NAME_SORA + TXT_KEY_CITY_NAME_INTERRAMA + TXT_KEY_CITY_NAME_SUESSA + TXT_KEY_CITY_NAME_SATICULA + TXT_KEY_CITY_NAME_LUCERIA + TXT_KEY_CITY_NAME_ARMINIUM + TXT_KEY_CITY_NAME_SENAGALLICA + TXT_KEY_CITY_NAME_CASTRUMNOVUM + TXT_KEY_CITY_NAME_HADRIA + + + + BUILDINGCLASS_MARKET + BUILDING_ROMAN_FORUM + + + + + UNITCLASS_SWORDSMAN + UNIT_ROME_PRAETORIAN + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_FISHING + 1 + + + TECH_MINING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_JULIUS_CAESAR + 1 + + + LEADER_AUGUSTUS + 1 + + + CIVILIZATION_BYZANTIUM + AS3D_ROME_SELECT + AS3D_ROME_ORDER + + + + CIVILIZATION_RUSSIA + TXT_KEY_CIV_RUSSIA_DESC + TXT_KEY_CIV_RUSSIA_SHORT_DESC + TXT_KEY_CIV_RUSSIA_ADJECTIVE + TXT_KEY_CIV_RUSSIA_PEDIA + PLAYERCOLOR_DARK_RED + ART_DEF_CIVILIZATION_RUSSIA + ARTSTYLE_EUROPEAN + UNIT_ARTSTYLE_EUROPEAN + 1 + 1 + + TXT_KEY_CITY_NAME_MOSCOW + TXT_KEY_CITY_NAME_STPETERSBURG + TXT_KEY_CITY_NAME_NOVGOROD + TXT_KEY_CITY_NAME_ROSTOV + TXT_KEY_CITY_NAME_YAROSLAVI + TXT_KEY_CITY_NAME_YEKATERINBURG + TXT_KEY_CITY_NAME_YAKUTSK + TXT_KEY_CITY_NAME_VLADIVOSTOK + TXT_KEY_CITY_NAME_SMOLENSK + TXT_KEY_CITY_NAME_ORENBURG + TXT_KEY_CITY_NAME_KRASNOYARSK + TXT_KEY_CITY_NAME_KHABAROVSK + TXT_KEY_CITY_NAME_BRYANSK + TXT_KEY_CITY_NAME_TVER + TXT_KEY_CITY_NAME_NOVOSIBIRSK + TXT_KEY_CITY_NAME_MAGADAN + TXT_KEY_CITY_NAME_MURMANSK + TXT_KEY_CITY_NAME_IRKUSTK + TXT_KEY_CITY_NAME_CHITA + TXT_KEY_CITY_NAME_SAMARA + TXT_KEY_CITY_NAME_ARKHANGELSK + TXT_KEY_CITY_NAME_CHELYABINSK + TXT_KEY_CITY_NAME_TOBOLSK + TXT_KEY_CITY_NAME_VOLOGDA + TXT_KEY_CITY_NAME_OMSK + TXT_KEY_CITY_NAME_ASTRAKHAN + TXT_KEY_CITY_NAME_KURSK + TXT_KEY_CITY_NAME_SARATOV + TXT_KEY_CITY_NAME_TULA + TXT_KEY_CITY_NAME_VLADIMIR + TXT_KEY_CITY_NAME_PERM + TXT_KEY_CITY_NAME_VORONEZH + TXT_KEY_CITY_NAME_PSKOV + TXT_KEY_CITY_NAME_STARAYARUSSA + TXT_KEY_CITY_NAME_KOSTROMA + TXT_KEY_CITY_NAME_NIZHNIYNOVGOROD + TXT_KEY_CITY_NAME_SUZDAL + TXT_KEY_CITY_NAME_MAGNITOGORSK + + + + BUILDINGCLASS_LABORATORY + BUILDING_RUSSIAN_RESEARCH_INSTITUTE + + + + + UNITCLASS_CAVALRY + UNIT_RUSSIA_COSSACK + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_HUNTING + 1 + + + TECH_MINING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_PETER + 1 + + + LEADER_CATHERINE + 1 + + + LEADER_STALIN + 1 + + + NONE + AS3D_RUSSIA_SELECT + AS3D_RUSSIA_ORDER + + + + CIVILIZATION_SPAIN + TXT_KEY_CIV_SPAIN_DESC + TXT_KEY_CIV_SPAIN_SHORT_DESC + TXT_KEY_CIV_SPAIN_ADJECTIVE + TXT_KEY_CIV_SPAIN_PEDIA + PLAYERCOLOR_PINK + ART_DEF_CIVILIZATION_SPAIN + ARTSTYLE_EUROPEAN + UNIT_ARTSTYLE_EUROPEAN + 1 + 1 + + TXT_KEY_CITY_NAME_MADRID + TXT_KEY_CITY_NAME_BARCELONA + TXT_KEY_CITY_NAME_SEVILLE + TXT_KEY_CITY_NAME_CORDOBA + TXT_KEY_CITY_NAME_TOLEDO + TXT_KEY_CITY_NAME_SANTIAGO + TXT_KEY_CITY_NAME_SALAMANCA + TXT_KEY_CITY_NAME_MURCIA + TXT_KEY_CITY_NAME_VALENCIA + TXT_KEY_CITY_NAME_ZARAGOZA + TXT_KEY_CITY_NAME_PAMPLONA + TXT_KEY_CITY_NAME_VITORIA + TXT_KEY_CITY_NAME_SANTANDER + TXT_KEY_CITY_NAME_ASTURIAS + TXT_KEY_CITY_NAME_JAEN + TXT_KEY_CITY_NAME_LOGRONO + TXT_KEY_CITY_NAME_VALLADOLID + TXT_KEY_CITY_NAME_PALMA + TXT_KEY_CITY_NAME_TERUEL + TXT_KEY_CITY_NAME_ALMERIA + TXT_KEY_CITY_NAME_LEON + TXT_KEY_CITY_NAME_ZAMORA + TXT_KEY_CITY_NAME_MIDA + TXT_KEY_CITY_NAME_LUGO + TXT_KEY_CITY_NAME_ALICANTE + TXT_KEY_CITY_NAME_CADIZ + TXT_KEY_CITY_NAME_ELCHE + TXT_KEY_CITY_NAME_ALCORCON + TXT_KEY_CITY_NAME_BURGOS + TXT_KEY_CITY_NAME_VIGO + TXT_KEY_CITY_NAME_BADAJOZ + TXT_KEY_CITY_NAME_LA_CORUNA + TXT_KEY_CITY_NAME_OVIEDO + TXT_KEY_CITY_NAME_BILBAO + TXT_KEY_CITY_NAME_SAN_SEBASTIAN + TXT_KEY_CITY_NAME_GRANADA + TXT_KEY_CITY_NAME_MERIDA + TXT_KEY_CITY_NAME_HUELVA + TXT_KEY_CITY_NAME_IBIZA + TXT_KEY_CITY_NAME_LAS_PALMAS + TXT_KEY_CITY_NAME_TENERIFE + + + + BUILDINGCLASS_CASTLE + BUILDING_SPANISH_CITADEL + + + + + UNITCLASS_CUIRASSIER + UNIT_SPANISH_CONQUISTADOR + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_FISHING + 1 + + + TECH_MYSTICISM + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_ISABELLA + 1 + + + CIVILIZATION_AMERICA + AS3D_SPAIN_SELECT + AS3D_SPAIN_ORDER + + + + CIVILIZATION_SUMERIA + TXT_KEY_CIV_SUMERIA_DESC + TXT_KEY_CIV_SUMERIA_SHORT_DESC + TXT_KEY_CIV_SUMERIA_ADJECTIVE + TXT_KEY_CIV_SUMERIA_PEDIA + PLAYERCOLOR_DARK_INDIGO + ART_DEF_CIVILIZATION_SUMERIA + ARTSTYLE_MIDDLE_EAST + UNIT_ARTSTYLE_MIDDLE_EAST + 1 + 1 + + TXT_KEY_CITY_NAME_URUK + TXT_KEY_CITY_NAME_ERIDU + TXT_KEY_CITY_NAME_KISH + TXT_KEY_CITY_NAME_LAGASH + TXT_KEY_CITY_NAME_UR + TXT_KEY_CITY_NAME_NIBRU + TXT_KEY_CITY_NAME_BAD_TIBIRA + TXT_KEY_CITY_NAME_ZIMBIR + TXT_KEY_CITY_NAME_SHURUPPAK + TXT_KEY_CITY_NAME_UMMA + TXT_KEY_CITY_NAME_LARSA + TXT_KEY_CITY_NAME_ISIN + TXT_KEY_CITY_NAME_GIRSU + TXT_KEY_CITY_NAME_ADAB + TXT_KEY_CITY_NAME_ZABALAM + TXT_KEY_CITY_NAME_AKSHAK + TXT_KEY_CITY_NAME_LARAK + TXT_KEY_CITY_NAME_KISIGA + TXT_KEY_CITY_NAME_NINA + TXT_KEY_CITY_NAME_DILBAT + TXT_KEY_CITY_NAME_KUTU + TXT_KEY_CITY_NAME_MARAD + TXT_KEY_CITY_NAME_ENEGI + TXT_KEY_CITY_NAME_ABU_SALABIKH + TXT_KEY_CITY_NAME_KI_AN + TXT_KEY_CITY_NAME_PAZURISH_DAGAN + TXT_KEY_CITY_NAME_DABRUM + TXT_KEY_CITY_NAME_KISSURA + TXT_KEY_CITY_NAME_KUTALLU + TXT_KEY_CITY_NAME_NAGSU + TXT_KEY_CITY_NAME_KESH + TXT_KEY_CITY_NAME_ARATTA + TXT_KEY_CITY_NAME_DER + TXT_KEY_CITY_NAME_HAMAZI + TXT_KEY_CITY_NAME_APISADA + TXT_KEY_CITY_NAME_JEMDET_NASR + TXT_KEY_CITY_NAME_UBAID + + + + BUILDINGCLASS_COURTHOUSE + BUILDING_SUMERIAN_ZIGGURAT + + + + + UNITCLASS_AXEMAN + UNIT_SUMERIAN_VULTURE + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_AGRICULTURE + 1 + + + TECH_THE_WHEEL + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_GILGAMESH + 1 + + + CIVILIZATION_BABYLON + AS3D_SUMERIA_SELECT + AS3D_SUMERIA_ORDER + + + + CIVILIZATION_VIKING + TXT_KEY_CIV_VIKING_DESC + TXT_KEY_CIV_VIKING_SHORT_DESC + TXT_KEY_CIV_VIKING_ADJECTIVE + TXT_KEY_CHANGED_CIV_VIKING_PEDIA + PLAYERCOLOR_LIGHT_PURPLE + ART_DEF_CIVILIZATION_VIKINGS + ARTSTYLE_EUROPEAN + UNIT_ARTSTYLE_EUROPEAN + 1 + 1 + + TXT_KEY_CITY_NAME_NIDAROS + TXT_KEY_CITY_NAME_UPPSALA + TXT_KEY_CITY_NAME_HAITHABU + TXT_KEY_CITY_NAME_BIRKA + TXT_KEY_CITY_NAME_BJORGVIN + TXT_KEY_CITY_NAME_JELLING + TXT_KEY_CITY_NAME_ROSKILDE + TXT_KEY_CITY_NAME_TONSBERG + TXT_KEY_CITY_NAME_SIGTUNA + TXT_KEY_CITY_NAME_LODOSE + TXT_KEY_CITY_NAME_ODENSE + TXT_KEY_CITY_NAME_OSLO + TXT_KEY_CITY_NAME_RIBE + TXT_KEY_CITY_NAME_LINDHOLM + TXT_KEY_CITY_NAME_VASTERAS + TXT_KEY_CITY_NAME_AARHUS + TXT_KEY_CITY_NAME_LUND + TXT_KEY_CITY_NAME_KAUPANG + TXT_KEY_CITY_NAME_REYKJAVIK + TXT_KEY_CITY_NAME_THINGVELLIR + TXT_KEY_CITY_NAME_JORVIK + TXT_KEY_CITY_NAME_LINCOLN + TXT_KEY_CITY_NAME_DEORABY + TXT_KEY_CITY_NAME_STAMFORD + TXT_KEY_CITY_NAME_DYFLIN + TXT_KEY_CITY_NAME_VADREJFORD + TXT_KEY_CITY_NAME_LIMERICK + TXT_KEY_CITY_NAME_ROWANE + TXT_KEY_CITY_NAME_KONUGARD + TXT_KEY_CITY_NAME_HOLMGARD + TXT_KEY_CITY_NAME_ALDEIGJUBORG + TXT_KEY_CITY_NAME_KIRKJUVAGR + TXT_KEY_CITY_NAME_TYNWALD + TXT_KEY_CITY_NAME_LEIRVIK + TXT_KEY_CITY_NAME_TINGANES + TXT_KEY_CITY_NAME_KIRKJUBOUR + TXT_KEY_CITY_NAME_BRATTAHLID + TXT_KEY_CITY_NAME_VINLAND + TXT_KEY_CITY_NAME_THUNDERFALL + + + + BUILDINGCLASS_LIGHTHOUSE + BUILDING_VIKING_TRADING_POST + + + + + UNITCLASS_MACEMAN + UNIT_VIKING_BESERKER + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_FISHING + 1 + + + TECH_HUNTING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_RAGNAR + 1 + + + CIVILIZATION_AMERICA + AS3D_VIKING_SELECT + AS3D_VIKING_ORDER + + + + CIVILIZATION_ZULU + TXT_KEY_CIV_ZULU_DESC + TXT_KEY_CIV_ZULU_SHORT_DESC + TXT_KEY_CIV_ZULU_ADJECTIVE + TXT_KEY_CIV_ZULU_PEDIA + PLAYERCOLOR_LIGHT_YELLOW + ART_DEF_CIVILIZATION_ZULU + ARTSTYLE_MIDDLE_EAST + UNIT_ARTSTYLE_MIDDLE_EAST + 1 + 1 + + TXT_KEY_CITY_NAME_ULUNDI + TXT_KEY_CITY_NAME_UMGUNGUNDLOVU + TXT_KEY_CITY_NAME_NOBAMBA + TXT_KEY_CITY_NAME_BULAWAYO + TXT_KEY_CITY_NAME_KWADUKUZA + TXT_KEY_CITY_NAME_NONGOMA + TXT_KEY_CITY_NAME_ONDINI + TXT_KEY_CITY_NAME_NODWENGU + TXT_KEY_CITY_NAME_NDONDAKUSUKA + TXT_KEY_CITY_NAME_BABANANGO + TXT_KEY_CITY_NAME_KHANGELA + TXT_KEY_CITY_NAME_KWAHLOMENDLINI + TXT_KEY_CITY_NAME_HLOBANE + TXT_KEY_CITY_NAME_ETHEKWINI + TXT_KEY_CITY_NAME_MLAMBONGWENYA + TXT_KEY_CITY_NAME_EZIQWAQWENI + TXT_KEY_CITY_NAME_EMANGWENI + TXT_KEY_CITY_NAME_ISIPHEZI + TXT_KEY_CITY_NAME_MASOTSHENI + TXT_KEY_CITY_NAME_MTUNZINI + TXT_KEY_CITY_NAME_NYAKAMUBI + TXT_KEY_CITY_NAME_DUMAZULU + TXT_KEY_CITY_NAME_HLATIKULU + TXT_KEY_CITY_NAME_MTHONJANENI + TXT_KEY_CITY_NAME_EMPANGENI + TXT_KEY_CITY_NAME_PONGOLA + TXT_KEY_CITY_NAME_TUNGELA + TXT_KEY_CITY_NAME_KWAMASHU + TXT_KEY_CITY_NAME_INGWAVUMA + TXT_KEY_CITY_NAME_HLUHLUWE + TXT_KEY_CITY_NAME_MTUBATUBA + TXT_KEY_CITY_NAME_MHLAHLANDLELA + TXT_KEY_CITY_NAME_MTHATHA + TXT_KEY_CITY_NAME_MASERU + TXT_KEY_CITY_NAME_LOBAMBA + TXT_KEY_CITY_NAME_QUNU + + + + BUILDINGCLASS_BARRACKS + BUILDING_ZULU_IKHANDA + + + + + UNITCLASS_SPEARMAN + UNIT_ZULU_IMPI + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_AGRICULTURE + 1 + + + TECH_HUNTING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_SHAKA + 1 + + + NONE + AS3D_ZULU_SELECT + AS3D_ZULU_ORDER + + + + CIVILIZATION_MINOR + TXT_KEY_CIV_MINOR_DESC + TXT_KEY_CIV_MINOR_SHORT_DESC + TXT_KEY_CIV_MINOR_ADJECTIVE + TXT_KEY_CIV_MINOR_PEDIA + PLAYERCOLOR_WHITE + ART_DEF_CIVILIZATION_MINOR + ARTSTYLE_BARBARIAN + 0 + 0 + + TXT_KEY_CITY_NAME_CHEROKEE + TXT_KEY_CITY_NAME_ANASAZI + TXT_KEY_CITY_NAME_TEOIHUACAN + TXT_KEY_CITY_NAME_OLMEC + TXT_KEY_CITY_NAME_ZAPOTEC + TXT_KEY_CITY_NAME_CHINOOK + TXT_KEY_CITY_NAME_APACHE + TXT_KEY_CITY_NAME_CHEHALIS + TXT_KEY_CITY_NAME_ILLINOIS + TXT_KEY_CITY_NAME_NAVAJO + TXT_KEY_CITY_NAME_CARIB + TXT_KEY_CITY_NAME_SAXON + TXT_KEY_CITY_NAME_VANDAL + TXT_KEY_CITY_NAME_GOTH + TXT_KEY_CITY_NAME_ANGLE + TXT_KEY_CITY_NAME_MAGYAR + TXT_KEY_CITY_NAME_KHAZAK + TXT_KEY_CITY_NAME_BULGAR + TXT_KEY_CITY_NAME_ALEMANNI + TXT_KEY_CITY_NAME_BURGUNDIAN + TXT_KEY_CITY_NAME_GEPID + TXT_KEY_CITY_NAME_HUN + TXT_KEY_CITY_NAME_JUTE + TXT_KEY_CITY_NAME_PHEONICIAN + TXT_KEY_CITY_NAME_ESTRUSCAN + TXT_KEY_CITY_NAME_THRACIAN + TXT_KEY_CITY_NAME_PHRYGIAN + TXT_KEY_CITY_NAME_GAUL + TXT_KEY_CITY_NAME_MINOAN + TXT_KEY_CITY_NAME_MYCENIAN + TXT_KEY_CITY_NAME_CIMMERIAN + TXT_KEY_CITY_NAME_LIGURIAN + TXT_KEY_CITY_NAME_NUMIDIAN + TXT_KEY_CITY_NAME_SARMATIAN + TXT_KEY_CITY_NAME_SCYTHIAN + TXT_KEY_CITY_NAME_VISIGOTH + TXT_KEY_CITY_NAME_ASSYRIAN + TXT_KEY_CITY_NAME_HITTITE + TXT_KEY_CITY_NAME_HARAPPAN + TXT_KEY_CITY_NAME_MAURYAN + TXT_KEY_CITY_NAME_PARTHIAN + TXT_KEY_CITY_NAME_HARAPPAN + TXT_KEY_CITY_NAME_NUBIAN + TXT_KEY_CITY_NAME_BACTRIAN + TXT_KEY_CITY_NAME_CIRCASSIAN + TXT_KEY_CITY_NAME_CUMAN + TXT_KEY_CITY_NAME_HURRIAN + TXT_KEY_CITY_NAME_KASSITE + TXT_KEY_CITY_NAME_BANTU + TXT_KEY_CITY_NAME_KHOISAN + TXT_KEY_CITY_NAME_LIBYAN + TXT_KEY_CITY_NAME_SHANGIAN + TXT_KEY_CITY_NAME_YAYOI + TXT_KEY_CITY_NAME_ZHOU + TXT_KEY_CITY_NAME_AINU + TXT_KEY_CITY_NAME_POLYNESIAN + TXT_KEY_CITY_NAME_ARYAN + TXT_KEY_CITY_NAME_AVAR + TXT_KEY_CITY_NAME_GHUZZ + TXT_KEY_CITY_NAME_HSUNGNU + TXT_KEY_CITY_NAME_KUSHANS + TXT_KEY_CITY_NAME_YUECHI + TXT_KEY_CITY_NAME_SAKAE + TXT_KEY_CITY_NAME_UZBEK + TXT_KEY_CITY_NAME_TARTAR + + + + + + UNITCLASS_SETTLER + 1 + + + + + BUILDINGCLASS_PALACE + 1 + + + + + TECH_MINING + 1 + + + TECH_MYSTICISM + 1 + + + TECH_FISHING + 1 + + + TECH_THE_WHEEL + 1 + + + TECH_AGRICULTURE + 1 + + + TECH_HUNTING + 1 + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_BARBARIAN + 1 + + + NONE + + + + + + CIVILIZATION_BARBARIAN + TXT_KEY_CIV_BARBARIAN_DESC + TXT_KEY_CIV_BARBARIAN_SHORT_DESC + TXT_KEY_CIV_BARBARIAN_ADJECTIVE + TXT_KEY_CIV_BARBARIAN_PEDIA + PLAYERCOLOR_BLACK + ART_DEF_CIVILIZATION_BARBARIAN + ARTSTYLE_BARBARIAN + 0 + 0 + + TXT_KEY_CITY_NAME_CHEROKEE + TXT_KEY_CITY_NAME_ANASAZI + TXT_KEY_CITY_NAME_TEOIHUACAN + TXT_KEY_CITY_NAME_OLMEC + TXT_KEY_CITY_NAME_ZAPOTEC + TXT_KEY_CITY_NAME_CHINOOK + TXT_KEY_CITY_NAME_APACHE + TXT_KEY_CITY_NAME_CHEHALIS + TXT_KEY_CITY_NAME_ILLINOIS + TXT_KEY_CITY_NAME_NAVAJO + TXT_KEY_CITY_NAME_CARIB + TXT_KEY_CITY_NAME_SAXON + TXT_KEY_CITY_NAME_VANDAL + TXT_KEY_CITY_NAME_GOTH + TXT_KEY_CITY_NAME_ANGLE + TXT_KEY_CITY_NAME_MAGYAR + TXT_KEY_CITY_NAME_KHAZAK + TXT_KEY_CITY_NAME_BULGAR + TXT_KEY_CITY_NAME_ALEMANNI + TXT_KEY_CITY_NAME_BURGUNDIAN + TXT_KEY_CITY_NAME_GEPID + TXT_KEY_CITY_NAME_HUN + TXT_KEY_CITY_NAME_JUTE + TXT_KEY_CITY_NAME_PHEONICIAN + TXT_KEY_CITY_NAME_ESTRUSCAN + TXT_KEY_CITY_NAME_THRACIAN + TXT_KEY_CITY_NAME_PHRYGIAN + TXT_KEY_CITY_NAME_GAUL + TXT_KEY_CITY_NAME_MINOAN + TXT_KEY_CITY_NAME_MYCENIAN + TXT_KEY_CITY_NAME_CIMMERIAN + TXT_KEY_CITY_NAME_LIGURIAN + TXT_KEY_CITY_NAME_NUMIDIAN + TXT_KEY_CITY_NAME_SARMATIAN + TXT_KEY_CITY_NAME_SCYTHIAN + TXT_KEY_CITY_NAME_VISIGOTH + TXT_KEY_CITY_NAME_ASSYRIAN + TXT_KEY_CITY_NAME_HITTITE + TXT_KEY_CITY_NAME_HARAPPAN + TXT_KEY_CITY_NAME_MAURYAN + TXT_KEY_CITY_NAME_PARTHIAN + TXT_KEY_CITY_NAME_HARAPPAN + TXT_KEY_CITY_NAME_NUBIAN + TXT_KEY_CITY_NAME_BACTRIAN + TXT_KEY_CITY_NAME_CIRCASSIAN + TXT_KEY_CITY_NAME_CUMAN + TXT_KEY_CITY_NAME_HURRIAN + TXT_KEY_CITY_NAME_KASSITE + TXT_KEY_CITY_NAME_BANTU + TXT_KEY_CITY_NAME_KHOISAN + TXT_KEY_CITY_NAME_LIBYAN + TXT_KEY_CITY_NAME_SHANGIAN + TXT_KEY_CITY_NAME_YAYOI + TXT_KEY_CITY_NAME_ZHOU + TXT_KEY_CITY_NAME_AINU + TXT_KEY_CITY_NAME_POLYNESIAN + TXT_KEY_CITY_NAME_ARYAN + TXT_KEY_CITY_NAME_AVAR + TXT_KEY_CITY_NAME_GHUZZ + TXT_KEY_CITY_NAME_HSUNGNU + TXT_KEY_CITY_NAME_KUSHANS + TXT_KEY_CITY_NAME_YUECHI + TXT_KEY_CITY_NAME_SAKAE + TXT_KEY_CITY_NAME_UZBEK + TXT_KEY_CITY_NAME_TARTAR + + + + BUILDINGCLASS_PALACE + NONE + + + BUILDINGCLASS_GREAT_PALACE + NONE + + + BUILDINGCLASS_VERSAILLES + NONE + + + BUILDINGCLASS_ACADEMY + NONE + + + BUILDINGCLASS_LIBRARY + NONE + + + BUILDINGCLASS_UNIVERSITY + NONE + + + BUILDINGCLASS_OBSERVATORY + NONE + + + BUILDINGCLASS_LABORATORY + NONE + + + BUILDINGCLASS_THEATRE + NONE + + + BUILDINGCLASS_BROADCAST_TOWER + NONE + + + BUILDINGCLASS_INTELLIGENCE_AGENCY + NONE + + + BUILDINGCLASS_NATIONAL_SECURITY + NONE + + + BUILDINGCLASS_JEWISH_TEMPLE + NONE + + + BUILDINGCLASS_JEWISH_CATHEDRAL + NONE + + + BUILDINGCLASS_JEWISH_MONASTERY + NONE + + + BUILDINGCLASS_JEWISH_SHRINE + NONE + + + BUILDINGCLASS_CHRISTIAN_TEMPLE + NONE + + + BUILDINGCLASS_CHRISTIAN_CATHEDRAL + NONE + + + BUILDINGCLASS_CHRISTIAN_MONASTERY + NONE + + + BUILDINGCLASS_CHRISTIAN_SHRINE + NONE + + + BUILDINGCLASS_ISLAMIC_TEMPLE + NONE + + + BUILDINGCLASS_ISLAMIC_CATHEDRAL + NONE + + + BUILDINGCLASS_ISLAMIC_MONASTERY + NONE + + + BUILDINGCLASS_ISLAMIC_SHRINE + NONE + + + BUILDINGCLASS_HINDU_TEMPLE + NONE + + + BUILDINGCLASS_HINDU_CATHEDRAL + NONE + + + BUILDINGCLASS_HINDU_MONASTERY + NONE + + + BUILDINGCLASS_HINDU_SHRINE + NONE + + + BUILDINGCLASS_BUDDHIST_TEMPLE + NONE + + + BUILDINGCLASS_BUDDHIST_CATHEDRAL + NONE + + + BUILDINGCLASS_BUDDHIST_MONASTERY + NONE + + + BUILDINGCLASS_BUDDHIST_SHRINE + NONE + + + BUILDINGCLASS_CONFUCIAN_TEMPLE + NONE + + + BUILDINGCLASS_CONFUCIAN_CATHEDRAL + NONE + + + BUILDINGCLASS_CONFUCIAN_MONASTERY + NONE + + + BUILDINGCLASS_CONFUCIAN_SHRINE + NONE + + + BUILDINGCLASS_TAOIST_TEMPLE + NONE + + + BUILDINGCLASS_TAOIST_CATHEDRAL + NONE + + + BUILDINGCLASS_TAOIST_MONASTERY + NONE + + + BUILDINGCLASS_TAOIST_SHRINE + NONE + + + BUILDINGCLASS_HEROIC_EPIC + NONE + + + BUILDINGCLASS_NATIONAL_EPIC + NONE + + + BUILDINGCLASS_GLOBE_THEATRE + NONE + + + BUILDINGCLASS_HERMITAGE + NONE + + + BUILDINGCLASS_OXFORD_UNIVERSITY + NONE + + + BUILDINGCLASS_WALL_STREET + NONE + + + BUILDINGCLASS_IRON_WORKS + NONE + + + BUILDINGCLASS_MT_RUSHMORE + NONE + + + BUILDINGCLASS_NATIONAL_PARK + NONE + + + BUILDINGCLASS_MOAI_STATUES + NONE + + + BUILDINGCLASS_RED_CROSS + NONE + + + BUILDINGCLASS_SCOTLAND_YARD + NONE + + + BUILDINGCLASS_WEST_POINT + NONE + + + BUILDINGCLASS_GREAT_LIBRARY + NONE + + + BUILDINGCLASS_GREAT_LIGHTHOUSE + NONE + + + BUILDINGCLASS_ORACLE + NONE + + + BUILDINGCLASS_STONEHENGE + NONE + + + BUILDINGCLASS_PARTHENON + NONE + + + BUILDINGCLASS_ANGKOR_WAT + NONE + + + BUILDINGCLASS_HAGIA_SOPHIA + NONE + + + BUILDINGCLASS_CHICHEN_ITZA + NONE + + + BUILDINGCLASS_SISTINE_CHAPEL + NONE + + + BUILDINGCLASS_SPIRAL_MINARET + NONE + + + BUILDINGCLASS_NOTRE_DAME + NONE + + + BUILDINGCLASS_TAJ_MAHAL + NONE + + + BUILDINGCLASS_KREMLIN + NONE + + + BUILDINGCLASS_EIFFEL_TOWER + NONE + + + BUILDINGCLASS_STATUE_OF_LIBERTY + NONE + + + BUILDINGCLASS_BROADWAY + NONE + + + BUILDINGCLASS_ROCKNROLL + NONE + + + BUILDINGCLASS_HOLLYWOOD + NONE + + + BUILDINGCLASS_GREAT_DAM + NONE + + + BUILDINGCLASS_PENTAGON + NONE + + + BUILDINGCLASS_UNITED_NATIONS + NONE + + + BUILDINGCLASS_SPACE_ELEVATOR + NONE + + + BUILDINGCLASS_COLOSSUS + NONE + + + BUILDINGCLASS_HANGING_GARDEN + NONE + + + BUILDINGCLASS_PYRAMID + NONE + + + BUILDINGCLASS_GREAT_WALL + NONE + + + BUILDINGCLASS_SANKORE + NONE + + + BUILDINGCLASS_ARTEMIS + NONE + + + BUILDINGCLASS_CRISTO_REDENTOR + NONE + + + BUILDINGCLASS_SHWEDAGON_PAYA + NONE + + + BUILDINGCLASS_MAUSOLEUM_OF_MAUSSOLLOS + NONE + + + BUILDINGCLASS_STATUE_OF_ZEUS + NONE + + + + + UNITCLASS_SETTLER + NONE + + + UNITCLASS_SCOUT + NONE + + + UNITCLASS_EXPLORER + NONE + + + UNITCLASS_JEWISH_MISSIONARY + NONE + + + UNITCLASS_CHRISTIAN_MISSIONARY + NONE + + + UNITCLASS_ISLAMIC_MISSIONARY + NONE + + + UNITCLASS_HINDU_MISSIONARY + NONE + + + UNITCLASS_BUDDHIST_MISSIONARY + NONE + + + UNITCLASS_CONFUCIAN_MISSIONARY + NONE + + + UNITCLASS_TAOIST_MISSIONARY + NONE + + + UNITCLASS_EXECUTIVE_1 + NONE + + + UNITCLASS_EXECUTIVE_2 + NONE + + + UNITCLASS_EXECUTIVE_3 + NONE + + + UNITCLASS_EXECUTIVE_4 + NONE + + + UNITCLASS_EXECUTIVE_5 + NONE + + + UNITCLASS_EXECUTIVE_6 + NONE + + + UNITCLASS_EXECUTIVE_7 + NONE + + + UNITCLASS_PIKEMAN + NONE + + + UNITCLASS_MUSKETMAN + NONE + + + UNITCLASS_INFANTRY + NONE + + + UNITCLASS_SAM_INFANTRY + NONE + + + UNITCLASS_MARINE + NONE + + + UNITCLASS_MECHANIZED_INFANTRY + NONE + + + UNITCLASS_CROSSBOWMAN + NONE + + + UNITCLASS_CHARIOT + NONE + + + UNITCLASS_KNIGHT + NONE + + + UNITCLASS_CUIRASSIER + NONE + + + UNITCLASS_CAVALRY + NONE + + + UNITCLASS_WAR_ELEPHANT + NONE + + + UNITCLASS_TANK + NONE + + + UNITCLASS_MODERN_ARMOR + NONE + + + UNITCLASS_GUNSHIP + NONE + + + UNITCLASS_CATAPULT + NONE + + + UNITCLASS_TREBUCHET + NONE + + + UNITCLASS_CANNON + NONE + + + UNITCLASS_MACHINE_GUN + NONE + + + UNITCLASS_ARTILLERY + NONE + + + UNITCLASS_MOBILE_ARTILLERY + NONE + + + UNITCLASS_MOBILE_SAM + NONE + + + UNITCLASS_AT_INFANTRY + NONE + + + UNITCLASS_WORKBOAT + NONE + + + UNITCLASS_TRIREME + NONE + + + UNITCLASS_CARAVEL + NONE + + + UNITCLASS_GALLEON + NONE + + + UNITCLASS_IRONCLAD + NONE + + + UNITCLASS_SHIP_OF_THE_LINE + NONE + + + UNITCLASS_TRANSPORT + NONE + + + UNITCLASS_DESTROYER + NONE + + + UNITCLASS_STEALTH_DESTROYER + NONE + + + UNITCLASS_MISSILE_CRUISER + NONE + + + UNITCLASS_BATTLESHIP + NONE + + + UNITCLASS_SUBMARINE + NONE + + + UNITCLASS_ATTACK_SUBMARINE + NONE + + + UNITCLASS_CARRIER + NONE + + + UNITCLASS_AIRSHIP + NONE + + + UNITCLASS_FIGHTER + NONE + + + UNITCLASS_JET_FIGHTER + NONE + + + UNITCLASS_BOMBER + NONE + + + UNITCLASS_STEALTH_BOMBER + NONE + + + UNITCLASS_GUIDED_MISSILE + NONE + + + UNITCLASS_TACTICAL_NUKE + NONE + + + UNITCLASS_ICBM + NONE + + + UNITCLASS_PROPHET + NONE + + + UNITCLASS_ARTIST + NONE + + + UNITCLASS_SCIENTIST + NONE + + + UNITCLASS_MERCHANT + NONE + + + UNITCLASS_ENGINEER + NONE + + + UNITCLASS_GREAT_SPY + NONE + + + + + + + + CIVIC_DESPOTISM + CIVIC_BARBARISM + CIVIC_TRIBALISM + CIVIC_DECENTRALIZATION + CIVIC_PAGANISM + + + + LEADER_BARBARIAN + 1 + + + NONE + + + + + diff --git a/Mod/Observer/Assets/XML/Civilizations/CIV4CivilizationsSchema.xml b/Mod/Observer/Assets/XML/Civilizations/CIV4CivilizationsSchema.xml index f7ca47e..8818ab5 100644 --- a/Mod/Observer/Assets/XML/Civilizations/CIV4CivilizationsSchema.xml +++ b/Mod/Observer/Assets/XML/Civilizations/CIV4CivilizationsSchema.xml @@ -334,6 +334,7 @@ + @@ -432,6 +433,7 @@ + diff --git a/Mod/Observer/Assets/XML/GameInfo/CIV4CivicInfos.xml b/Mod/Observer/Assets/XML/GameInfo/CIV4CivicInfos.xml new file mode 100644 index 0000000..e5d9a82 --- /dev/null +++ b/Mod/Observer/Assets/XML/GameInfo/CIV4CivicInfos.xml @@ -0,0 +1,1934 @@ + + + + + + + + + + CIVICOPTION_GOVERNMENT + CIVIC_DESPOTISM + TXT_KEY_CIVIC_DESPOTISM + TXT_KEY_CIVIC_DESPOTISM_PEDIA + TXT_KEY_CIVIC_DESPOTISM_STRATEGY + + NONE + 1 + UPKEEP_LOW + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + TXT_KEY_CIVIC_WE_LOVE_DESPOT + + + CIVICOPTION_GOVERNMENT + CIVIC_HEREDITARY_RULE + TXT_KEY_CIVIC_HEREDITARY_RULE + TXT_KEY_CIVIC_HEREDITARY_RULE_PEDIA + TXT_KEY_CIVIC_HEREDITARY_RULE_STRATEGY + + TECH_MONARCHY + 1 + UPKEEP_LOW + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + TXT_KEY_CIVIC_WE_LOVE_MONARCH + + + CIVICOPTION_GOVERNMENT + CIVIC_REPRESENTATION + TXT_KEY_CIVIC_REPRESENTATION + TXT_KEY_CIVIC_REPRESENTATION_PEDIA + TXT_KEY_CIVIC_REPRESENTATION_STRATEGY + + TECH_CONSTITUTION + 1 + UPKEEP_MEDIUM + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + 0 + 3 + 0 + + + + + + + + + + + + + + + + TXT_KEY_CIVIC_WE_LOVE_PRIME_MINISTER + + + CIVICOPTION_GOVERNMENT + CIVIC_POLICE_STATE + TXT_KEY_CIVIC_POLICE_STATE + TXT_KEY_CIVIC_POLICE_STATE_PEDIA + TXT_KEY_CIVIC_POLICE_STATE_STRATEGY + + TECH_FASCISM + 1 + UPKEEP_HIGH + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 25 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + -50 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + TXT_KEY_CIVIC_WE_LOVE_DICTATOR + + + CIVICOPTION_GOVERNMENT + CIVIC_UNIVERSAL_SUFFRAGE + TXT_KEY_CIVIC_UNIVERSAL_SUFFRAGE + TXT_KEY_CIVIC_UNIVERSAL_SUFFRAGE_PEDIA + TXT_KEY_CIVIC_UNIVERSAL_SUFFRAGE_STRATEGY + + TECH_DEMOCRACY + 1 + UPKEEP_MEDIUM + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + HURRY_GOLD + 1 + + + + + + + + + + + + + + + + + IMPROVEMENT_TOWN + + 0 + 1 + 0 + + + + TXT_KEY_CIVIC_WE_LOVE_PRESIDENT + + + CIVICOPTION_LEGAL + CIVIC_BARBARISM + TXT_KEY_CIVIC_BARBARISM + TXT_KEY_CIVIC_BARBARISM_PEDIA + TXT_KEY_CIVIC_BARBARISM_STRATEGY + + NONE + 1 + UPKEEP_LOW + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + CIVICOPTION_LEGAL + CIVIC_VASSALAGE + TXT_KEY_CIVIC_VASSALAGE + TXT_KEY_CIVIC_VASSALAGE_PEDIA + TXT_KEY_CIVIC_VASSALAGE_STRATEGY + + TECH_FEUDALISM + 1 + UPKEEP_HIGH + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 5 + 0 + 10 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + CIVICOPTION_LEGAL + CIVIC_BUREAUCRACY + TXT_KEY_CIVIC_BUREAUCRACY + TXT_KEY_CIVIC_BUREAUCRACY_PEDIA + TXT_KEY_CIVIC_BUREAUCRACY_STRATEGY + + TECH_CIVIL_SERVICE + 1 + UPKEEP_HIGH + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 0 + 50 + 50 + + + + + + + + + + + + + + + + + + + + + + + CIVICOPTION_LEGAL + CIVIC_NATIONHOOD + TXT_KEY_CIVIC_NATIONHOOD + TXT_KEY_CIVIC_NATIONHOOD_PEDIA + TXT_KEY_CIVIC_NATIONHOOD_STRATEGY + + TECH_NATIONALISM + 1 + NONE + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + 0 + 0 + 0 + 25 + + + + + + + + + BUILDINGCLASS_BARRACKS + 2 + + + + + + + + + + + + + + + + CIVICOPTION_LEGAL + CIVIC_FREE_SPEECH + TXT_KEY_CIVIC_FREE_SPEECH + TXT_KEY_CIVIC_FREE_SPEECH_PEDIA + TXT_KEY_CIVIC_FREE_SPEECH_STRATEGY + + TECH_LIBERALISM + 1 + UPKEEP_LOW + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + 0 + 0 + 100 + + + + + + + + + + + + + + + + + + + IMPROVEMENT_TOWN + + 0 + 0 + 2 + + + + + + + CIVICOPTION_LABOR + CIVIC_TRIBALISM + TXT_KEY_CIVIC_TRIBALISM + TXT_KEY_CIVIC_TRIBALISM_PEDIA + TXT_KEY_CIVIC_TRIBALISM_STRATEGY + + NONE + 1 + UPKEEP_LOW + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + CIVICOPTION_LABOR + CIVIC_SLAVERY + TXT_KEY_CIVIC_SLAVERY + TXT_KEY_CIVIC_SLAVERY_PEDIA + TXT_KEY_CIVIC_SLAVERY_STRATEGY + + TECH_BRONZE_WORKING + 1 + UPKEEP_MEDIUM + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + HURRY_POPULATION + 1 + + + + + + + + + + + + + + + + + + + CIVICOPTION_LABOR + CIVIC_SERFDOM + TXT_KEY_CIVIC_SERFDOM + TXT_KEY_CIVIC_SERFDOM_PEDIA + TXT_KEY_CIVIC_SERFDOM_STRATEGY + + TECH_FEUDALISM + 1 + UPKEEP_LOW + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 50 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + CIVICOPTION_LABOR + CIVIC_CASTE_SYSTEM + TXT_KEY_CIVIC_CASTE_SYSTEM + TXT_KEY_CIVIC_CASTE_SYSTEM_PEDIA + TXT_KEY_CIVIC_CASTE_SYSTEM_STRATEGY + + TECH_CODE_OF_LAWS + 1 + UPKEEP_MEDIUM + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + SPECIALIST_ARTIST + 1 + + + SPECIALIST_SCIENTIST + 1 + + + SPECIALIST_MERCHANT + 1 + + + + + + + + + + + + + + + IMPROVEMENT_WORKSHOP + + 0 + 1 + 0 + + + + + + + CIVICOPTION_LABOR + CIVIC_EMANCIPATION + TXT_KEY_CIVIC_EMANCIPATION + TXT_KEY_CIVIC_EMANCIPATION_PEDIA + TXT_KEY_CIVIC_EMANCIPATION_STRATEGY + + TECH_DEMOCRACY + 1 + UPKEEP_LOW + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 100 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 400 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + CIVICOPTION_ECONOMY + CIVIC_DECENTRALIZATION + TXT_KEY_CIVIC_DECENTRALIZATION + TXT_KEY_CIVIC_DECENTRALIZATION_PEDIA + TXT_KEY_CIVIC_DECENTRALIZATION_STRATEGY + + NONE + 1 + UPKEEP_LOW + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + CIVICOPTION_ECONOMY + CIVIC_MERCANTILISM + TXT_KEY_CIVIC_MERCANTILISM + TXT_KEY_CIVIC_MERCANTILISM_PEDIA + TXT_KEY_CIVIC_MERCANTILISM_STRATEGY + + TECH_BANKING + 1 + UPKEEP_MEDIUM + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + CIVICOPTION_ECONOMY + CIVIC_FREE_MARKET + TXT_KEY_CIVIC_FREE_MARKET + TXT_KEY_CIVIC_FREE_MARKET_PEDIA + TXT_KEY_CIVIC_FREE_MARKET_STRATEGY + + TECH_ECONOMICS + 1 + UPKEEP_MEDIUM + 0 + 0 + 0 + 0 + 0 + 0 + 0 + -25 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + CIVICOPTION_ECONOMY + CIVIC_STATE_PROPERTY + TXT_KEY_CIVIC_STATE_PROPERTY + TXT_KEY_CIVIC_STATE_PROPERTY_PEDIA + TXT_KEY_CIVIC_STATE_PROPERTY_STRATEGY + + TECH_UTOPIA + 1 + UPKEEP_LOW + 0 + 0 + 0 + 0 + 0 + -100 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0 + 10 + 0 + + + + + + + + + + + + + + + + + + + + + + IMPROVEMENT_WORKSHOP + + 1 + 0 + 0 + + + + IMPROVEMENT_WATERMILL + + 1 + 0 + 0 + + + + + + + CIVICOPTION_ECONOMY + CIVIC_ENVIRONMENTALISM + TXT_KEY_CIVIC_ENVIRONMENTALISM + TXT_KEY_CIVIC_ENVIRONMENTALISM_PEDIA + TXT_KEY_CIVIC_ENVIRONMENTALISM_STRATEGY + + TECH_MEDICINE + 1 + UPKEEP_MEDIUM + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 25 + 6 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + + + BUILDINGCLASS_PUBLIC_TRANSPORTATION + 2 + + + + + + + + + + + + + IMPROVEMENT_FOREST_PRESERVE + + 0 + 0 + 2 + + + + IMPROVEMENT_WINDMILL + + 0 + 0 + 2 + + + + + + + CIVICOPTION_RELIGION + CIVIC_PAGANISM + TXT_KEY_CIVIC_PAGANISM + TXT_KEY_CIVIC_PAGANISM_PEDIA + TXT_KEY_CIVIC_PAGANISM_STRATEGY + + NONE + 1 + UPKEEP_LOW + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + CIVICOPTION_RELIGION + CIVIC_ORGANIZED_RELIGION + TXT_KEY_CIVIC_ORGANIZED_RELIGION + TXT_KEY_CIVIC_ORGANIZED_RELIGION_PEDIA + TXT_KEY_CIVIC_ORGANIZED_RELIGION_STRATEGY + + TECH_MONOTHEISM + 1 + UPKEEP_HIGH + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 25 + 0 + + + + + + + + + + SPECIALBUILDING_MONASTERY + 1 + + + + + + + + + + + + + + + + + + CIVICOPTION_RELIGION + CIVIC_THEOCRACY + TXT_KEY_CIVIC_THEOCRACY + TXT_KEY_CIVIC_THEOCRACY_PEDIA + TXT_KEY_CIVIC_THEOCRACY_STRATEGY + + TECH_THEOLOGY + 1 + UPKEEP_MEDIUM + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 2 + + + + + + + + + + + + + + + + + + + + + + + + CIVICOPTION_RELIGION + CIVIC_PACIFISM + TXT_KEY_CIVIC_PACIFISM + TXT_KEY_CIVIC_PACIFISM_PEDIA + TXT_KEY_CIVIC_PACIFISM_STRATEGY + + TECH_PHILOSOPHY + 1 + NONE + 0 + 0 + 0 + 0 + 100 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + CIVICOPTION_RELIGION + CIVIC_FREE_RELIGION + TXT_KEY_CIVIC_FREE_RELIGION + TXT_KEY_CIVIC_FREE_RELIGION_PEDIA + TXT_KEY_CIVIC_FREE_RELIGION_STRATEGY + + TECH_LIBERALISM + 1 + UPKEEP_LOW + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + + + + 0 + 10 + 0 + + + + + + + + + + + + + + + + + + + + + diff --git a/Mod/Observer/Assets/XML/GameInfo/CIV4GameInfoSchema.xml b/Mod/Observer/Assets/XML/GameInfo/CIV4GameInfoSchema.xml new file mode 100644 index 0000000..e2347a8 --- /dev/null +++ b/Mod/Observer/Assets/XML/GameInfo/CIV4GameInfoSchema.xml @@ -0,0 +1,1425 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mod/Observer/Assets/XML/GlobalDefines.xml b/Mod/Observer/Assets/XML/GlobalDefines.xml index 5039bbe..520118a 100644 --- a/Mod/Observer/Assets/XML/GlobalDefines.xml +++ b/Mod/Observer/Assets/XML/GlobalDefines.xml @@ -1674,6 +1674,10 @@ TECH_COST_CIV_COUNT_HARD_CAP 0 + + TECH_COST_CIV_COUNT_HARD_CAP_LOWER + 0 + TECH_COST_MODIFIER_PER_ERA_MULTIPLIER 0 @@ -1722,5 +1726,24 @@ PITBOSS_PORTAL_LOG_DIRECTORY c:/temp - + + ENABLE_PITBOSS_PORTAL_GAMESTATE_LOGGING + 1 + + + ENABLE_EXTENDED_RECOVERY_SAVES + 1 + + + ENABLE_PITBOSS_PAUSE_FIX + 1 + + + TECH_COST_SCALING_ALGORITHM + 0 + + + EXTRA_SETTLED_GREAT_PEOPLE_FROM_PHI + 0 + diff --git a/Mod/Observer/Assets/XML/Terrain/CIV4TerrainSchema.xml b/Mod/Observer/Assets/XML/Terrain/CIV4TerrainSchema.xml new file mode 100644 index 0000000..69e2af8 --- /dev/null +++ b/Mod/Observer/Assets/XML/Terrain/CIV4TerrainSchema.xml @@ -0,0 +1,502 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mod/Observer/Assets/XML/Text/CIV4GameText_BTS_Fixed.xml b/Mod/Observer/Assets/XML/Text/CIV4GameText_BTS_Fixed.xml new file mode 100644 index 0000000..ddfac08 --- /dev/null +++ b/Mod/Observer/Assets/XML/Text/CIV4GameText_BTS_Fixed.xml @@ -0,0 +1,540 @@ + + + + + TXT_KEY_CONCEPT_SEA_TRADE_PEDIA_TR + [H1]Naval Trade Routes[\H1][PARAGRAPH:2]In Beyond the Sword, trade routes across water tiles can now be blockaded by enemy ships. The "Blockade Mission" can only be performed by Naval Units and is most effective when performed in close proximity to an enemy city. In general, this means that the "Blockade" mission works best between players at war. The lone exception to this rule is when players use the [LINK=UNIT_PRIVATEER]Privateer[\LINK] unit, which can effectively blockade at any time.[PARAGRAPH:1]By choosing the "Blockade Mission," a Naval Unit may prevent enemy trade routes from passing through the area which they are blockading, effectively preventing enemies from gaining any gold from that route. Blockaded regions appear as large striped zones stretching outward from the unit performing the mission. If an enemy city falls within this zone, players can ensure that no overseas trade will reach this city! If a city is blockaded by a Privateer while two nations are at peace, the blockading player will receive a portion of the gold from the blockaded routes. + [H1]Routes commerciales maritimes[\H1][PARAGRAPH:2]Dans Beyond the Sword, les routes commerciales qui traversent les cases de mer peuvent à présent être bloquées par les navires ennemis. La mission Blocus ne peut exécutée que par des unités navales et elle est d'une plus grande efficacité à proximité d'une ville ennemie. En général, cela signifie que la mission Blocus est plus efficace entre deux joueurs en guerre. La seule exception à cette règle survient quand l'un des joueurs utilise l'unité [LINK=UNIT_PRIVATEER]Corsaire[\LINK], qui peut effectuer des blocus n'importe quand.[PARAGRAPH:1]En choisissant la mission Blocus, une unité navale peut empêcher les routes commerciales ennemies de passer par la zone bloquée, privant l'ennemi de l'or que cette route peut rapporter. Les régions bloquées apparaissent comme de larges bandes s'étirant depuis l'unité exécutant cette mission. Si une ville ennemie se trouve dans cette zone, vous pouvez faire en sorte qu'aucun commerce maritime n'atteigne cette ville ! Si une ville subit un blocus par une unité de corsaires alors que deux nations sont en paix, le joueur faisant le blocus recevra une partie de l'or provenant des routes bloquées. + [H1]Marinehandelswege[\H1][PARAGRAPH:2]In Beyond the Sword können Handelswege über Wasser-Geländefelder nun von feindlichen Schiffen blockiert werden. Die Blockade-Mission kann nur von Marineeinheiten durchgeführt werden und ist am effektivsten in der Nähe einer gegnerischen Stadt. In der Regel ist die Blockade-Mission daher am besten für Spieler geeignet, die miteinander Krieg führen. Die einzige Ausnahme dieser Regel bildet die Einheit [LINK=UNIT_PRIVATEER]Freibeuter[\LINK], die zu jedem beliebigen Zeitpunkt Blockaden bilden kann.[PARAGRAPH:1]Wenn Sie die Blockade-Mission auswählen, kann eine Marineeinheit gegnerischen Handel im blockierten Gebiet verhindern, wodurch Gegner kein Gold von diesem Handelsweg erhalten. Blockierte Gebiete erscheinen als große gestreifte Zonen, die sich von der zur Blockade eingesetzten Einheit aus erstrecken. Wenn eine gegnerische Stadt in diesem Gebiet liegt, kann der Spieler sicherstellen, dass der Überseehandel diese Stadt nicht erreicht! Wenn eine Stadt von einem Freibeuter blockiert wird, während sich beide Nationen im Frieden befinden, erhält der blockierende Spieler einen Anteil des Goldes der blockierten Handelswege. + [H1]Rotte commerciali navali[\H1][PARAGRAPH:2]In Beyond the Sword, le rotte commerciali sulle caselle d'acqua ora possono essere bloccate dalle navi nemiche. La missione "Embargo" può essere compiuta solo da unità navali ed è più efficace in prossimità di una città nemica. Ciò vuol dire che, di norma, la missione "Embargo" funziona meglio tra giocatori in guerra. L'unica eccezione a questa regola è la [LINK=UNIT_PRIVATEER]nave corsara[\LINK], che può bloccare le rotte in qualsiasi momento.[PARAGRAPH:1]Selezionando la missione "Embargo", l'unità navale impedisce a quelle nemiche di seguire la rotta commerciale attraverso l'area bloccata, impedendo ai nemici di acquisire oro da quella rotta. Le regioni su cui è attivo l'embargo sono coperte da grosse strisce che si allungano a partire dall'unità che sta compiendo la missione. Se una città nemica ricade nell'area, il giocatore sarà sicuro che nessun bene esterno raggiungerà quella città! Se una città subisce l'embargo da parte di una nave corsara mentre le due nazioni sono in pace, il giocatore che sta effettuando l'embargo riceverà parte dell'oro che viaggia lungo la rotta bloccata. + [H1]Rutas comerciales navales[\H1][PARAGRAPH:2]En Beyond the Sword, los barcos enemigos pueden bloquear las rutas comerciales que cruzan las casillas de agua. La misión "Bloqueo" solo la pueden llevar a cabo las unidades navales y solo puede realizarse estando muy cerca de una ciudad enemiga. Por lo general, esto significa que la misión "Bloqueo" funciona mejor entre jugadores que estén en guerra. La única excepción a esta regla se da cuando los jugadores usan la unidad del [LINK=UNIT_PRIVATEER]Corsario[\LINK], que puede realizar un bloqueo en cualquier momento.[PARAGRAPH:1]Al elegir la misión "Bloqueo", una unidad naval puede impedir que las rutas comerciales pasen por el área que ella esté bloqueando, con lo que impide que el enemigo obtenga oro de esa ruta. Las regiones bloqueadas se muestran como grandes zonas rayadas que se tienden desde la unidad que esté llevando a cabo la misión. Si una ciudad enemiga se encuentra en esa zona, los jugadores se asegurarán de que ningún comercio de ultramar llegue hasta ella. Si un corsario bloquea una ciudad mientras las dos naciones están en paz, el jugador que realice el bloqueo recibirá una parte del oro proveniente de las rutas bloqueadas. + + + TXT_KEY_BTS_RULES_CHANGES_PEDIA_SR + [H1]Beyond the Sword Rules Changes[\H1][NEWLINE][NEWLINE][BOLD]Tech Changes[\BOLD][NEWLINE]Selecting the "No Tech Brokering" Option makes it impossible for players to trade Technologies that they have not researched themselves[NEWLINE][LINK=TECH_FIBER_OPTICS]Fiber Optics[\LINK] requires [LINK=TECH_LASER]Laser[\LINK] or [LINK=TECH_COMPUTERS]Computers[\LINK][NEWLINE][LINK=TECH_ROBOTICS]Robotics[\LINK] no longer directly requires [LINK=TECH_PLASTICS]Plastics[\LINK][NEWLINE][LINK=TECH_COMPUTERS]Computers[\LINK] requires [LINK=TECH_PLASTICS]Plastics[\LINK][NEWLINE][NEWLINE][BOLD]Building Changes[\BOLD][NEWLINE][LINK=BUILDING_AIRPORT]Airports[\LINK] provide +3 XP to all Air Units and allows four extra air units to be housed in a city (for a total of eight)[NEWLINE]The [LINK=BUILDING_PALACE]Palace[\LINK] provides +4 Espionage Points per turn[NEWLINE]The [LINK=BUILDING_COURTHOUSE]Courthouse[\LINK] provides +2 espionage points and 1 spy specialist[NEWLINE]The [LINK=BUILDING_CASTLE]Castle[\LINK] provides +25%% espionage points[NEWLINE]The [LINK=BUILDING_JAIL]Jail[\LINK] provides +4 espionage points, +50%% espionage points and 2 spy specialists[NEWLINE]The [LINK=BUILDING_LABORATORY]Laboratory[\LINK] requires [LINK=TECH_SUPERCONDUCTORS]Superconductor[\LINK][NEWLINE]The [LINK=BUILDING_FACTORY]Factory[\LINK] now causes Unhealthiness with access to Coal or Oil[NEWLINE]The [LINK=BUILDING_STABLE]Stable[\LINK] is made obsolete by [LINK=TECH_ADVANCED_FLIGHT]Advanced Flight[\LINK][NEWLINE][LINK=BUILDING_OBELISK]Monuments[\LINK] are made obsolete by [LINK=TECH_ASTRONOMY]Astronomy[\LINK][NEWLINE]The [LINK=BUILDING_MILITARY_ACADEMY]Military Academy[\LINK] can only be built after researching [LINK=TECH_MILITARY_SCIENCE]Military Science[\LINK][NEWLINE][NEWLINE][BOLD]Unit Changes[\BOLD][NEWLINE]Spies have been changed greatly. Visit [LINK=CONCEPT_ESPIONAGE]Espionage[\LINK] for more information[NEWLINE]Mounted and Helicopter Units now receive [LINK=CONCEPT_FLANK_ATTACK]Flank Attacks[\LINK] against Siege Weapons. See individual entries for further details[NEWLINE]The Japanese [LINK=UNIT_JAPAN_SAMURAI]Samurai[\LINK] now starts with the Drill I promotion[NEWLINE]The Greek [LINK=UNIT_GREEK_PHALANX]Phalanx[\LINK] replaces the [LINK=UNIT_AXEMAN]Axeman[\LINK][NEWLINE][LINK=UNIT_GRENADIER]Grenadier[\LINK] requires [LINK=TECH_MILITARY_SCIENCE]Military Science[\LINK], not [LINK=TECH_CHEMISTRY]Chemistry[\LINK][NEWLINE][LINK=UNIT_CAVALRY]Cavalry[\LINK] requires [LINK=TECH_RIFLING]Rifling[\LINK] in addition to [LINK=TECH_MILITARY_TRADITION]Military Tradition[\LINK][NEWLINE][LINK=UNIT_SAM_INFANTRY]SAM Infantry[\LINK] receive a 75%% bonus against Helicopter Units[NEWLINE]SAM units may receive the [LINK=CONCEPT_AIR_PROMOTIONS]Interception[\LINK] promotions[NEWLINE][LINK=UNIT_TRIREME]Trireme[\LINK] requires [LINK=TECH_METAL_CASTING]Metal Casting[\LINK][NEWLINE][LINK=UNIT_GUNSHIP]Gunships[\LINK] and [LINK=UNIT_JET_FIGHTER]Jet Fighters[\LINK] require only [LINK=TECH_ADVANCED_FLIGHT]Advanced Flight[\LINK][NEWLINE][LINK=CIVILIZATION_SPAIN]Spain[\LINK] can build [LINK=UNIT_KNIGHT]Knights[\LINK], as the [LINK=UNIT_SPANISH_CONQUISTADOR]Conquistador[\LINK] replaces the [LINK=UNIT_CUIRASSIER]Cuirassier[\LINK][NEWLINE]You may only house four air units in a city at a time. With an [LINK=BUILDING_AIRPORT]Airport[\LINK] building, you may house eight[NEWLINE]The amount of experience needed to produce successive [LINK=UNIT_GREAT_GENERAL]Great Generals[\LINK] has been increased[NEWLINE]Bombarding now reduces city defenses by a fixed amount, rather than a percentage[NEWLINE][NEWLINE][BOLD]Wonder Changes[\BOLD][NEWLINE][LINK=BUILDING_SCOTLAND_YARD]Scotland Yard[\LINK] may only be built by a [LINK=UNIT_GREAT_SPY]Great Spy[\LINK] and provides +100%% espionage and +2 Great Spy points[NEWLINE]The [LINK=BUILDING_PENTAGON]Pentagon[\LINK] provides +2 Great Spy points[NEWLINE]The [LINK=BUILDING_GREAT_PALACE]Forbidden Palace[\LINK] provides +1 Great Spy points[NEWLINE]The [LINK=BUILDING_KREMLIN]Kremlin[\LINK] allows the creations of 2 spy specialists and provides +2 Great Spy points[NEWLINE][LINK=BUILDING_WEST_POINT]West Point[\LINK] provides +2 Great Spy points[NEWLINE][LINK=BUILDING_GREAT_WALL]The Great Wall[\LINK] gives two Great People points (Great Spy)[NEWLINE]The [LINK=BUILDING_SISTINE_CHAPEL]Sistine Chapel[\LINK] provides +5 culture for every state religion building in a city and can be built after researching [LINK=TECH_MUSIC]Music[\LINK][NEWLINE][LINK=BUILDING_NOTRE_DAME]Notre Dame[\LINK] provides + 2 happiness to every city on its continent and can be built after researching [LINK=TECH_ENGINEERING]Engineering[\LINK][NEWLINE][LINK=BUILDING_PARTHENON]The Parthenon[\LINK] requires [LINK=TECH_AESTHETICS]Aesthetics[\LINK][NEWLINE]The [LINK=BUILDING_HAGIA_SOPHIA]Hagia Sophia[\LINK] requires [LINK=TECH_THEOLOGY]Theology[\LINK][NEWLINE][LINK=BUILDING_STONEHENGE]Stonehenge[\LINK] obsoletes with [LINK=TECH_ASTRONOMY]Astronomy[\LINK][NEWLINE]All National Wonders now provide +1 Great Person points instead of +2[NEWLINE][NEWLINE][BOLD]Civics Changes[\BOLD][NEWLINE][LINK=CIVIC_SLAVERY]Slavery's[\LINK] upkeep has been changed to Medium[NEWLINE][LINK=CIVIC_MERCANTILISM]Mercantilism[\LINK] causes Foreign Corporations to have no effect in your cities[NEWLINE][LINK=CIVIC_FREE_MARKET]Free Market[\LINK] reduces Corporation Maintenance by 25%%[NEWLINE][LINK=CIVIC_STATE_PROPERTY]State Property[\LINK] causes all Corporations to have no effect in your cities and provides a +10%% production bonus in all cities[NEWLINE][LINK=CIVIC_NATIONHOOD]Nationhood[\LINK] provides a +25%% bonus to Espionage Points[NEWLINE][LINK=CIVIC_CASTE_SYSTEM]Caste System[\LINK] provides a production bonus from Workshops[NEWLINE][LINK=CIVIC_ENVIRONMENTALISM]Environmentalism[\LINK] provides a commerce bonus from [LINK=CONCEPT_BTS_FOREST_PRESERVE]Forest Preserves[\LINK] and Windmills, but at the cost of a 25%% increase in Corporation Maintenance[NEWLINE][NEWLINE][BOLD]Project Changes[\BOLD][NEWLINE]You may view your Spaceship and its completed pieces on the Victory Screen[NEWLINE]A Spaceship can now be launched without all its casing complete, but each missing piece greatly increases the risk of failure[NEWLINE][LINK=PROJECT_SS_CASING]SS Casing[\LINK] requires [LINK=TECH_COMPOSITES]Composites[\LINK] in place of [LINK=TECH_ROCKETRY]Rocketry[\LINK][NEWLINE][LINK=PROJECT_SS_DOCKING_BAY]SS Docking Bay[\LINK] requires [LINK=TECH_SATELLITES]Satellites[\LINK] instead of [LINK=TECH_ROBOTICS]Robotics[\LINK][NEWLINE][LINK=PROJECT_SDI]SDI[\LINK] requires [LINK=TECH_LASER]Laser[\LINK][NEWLINE][LINK=PROJECT_THE_INTERNET]The Internet[\LINK] requires [LINK=TECH_COMPUTERS]Computers[\LINK][NEWLINE][LINK=PROJECT_SS_THRUSTERS]SS Thrusters[\LINK] require [LINK=TECH_SUPERCONDUCTORS]Superconductor[\LINK][NEWLINE]Spaceships now have a delayed arrival and may be launched with redundant systems for an increased chance of success or faster arrival time. They may also be launched with certain systems missing, but this increases the risk of failure[NEWLINE][NEWLINE][BOLD]Improvement Changes[\BOLD][NEWLINE]Forts have changed significantly. Visit the [LINK=CONCEPT_FORT]Forts[\LINK] section for an in-depth explanation[NEWLINE]Railroads can be built with Oil or Coal[NEWLINE][NEWLINE][BOLD]Interface Changes[\BOLD][NEWLINE]You may view your active Quests on the Log Screen [CTRL + TAB][NEWLINE]Foreign Advisor screen has been improved[NEWLINE]The Dawn of Man Screen has been expanded[NEWLINE]Elapsed Turns, Research per Turn and Espionage Points per Turn are displayed on the main interface[NEWLINE]Units in the Civilopedia display any Unique Units that replace them[NEWLINE]The Demographics Screen now shows the correct economic ranking[NEWLINE]Enemies entering your territory are marked with a red indicator[NEWLINE]Clicking your own score minimizes the list of leaders[NEWLINE]Pressing [CTRL + H] will select all wounded units in a specific tile[NEWLINE][NEWLINE][BOLD]Gameplay Changes[\BOLD][NEWLINE]Games on normal speed now last 500 turns, but the passage of time has been adjusted so the game still ends in 2050 AD[NEWLINE]The [LINK=BUILDING_UNITED_NATIONS]United Nations[\LINK] has been greatly expanded. Visit the [LINK=CONCEPT_APOSTOLIC_PALACE]Apostolic Palace[\LINK] Section for more details[NEWLINE]Golden Ages increase the Great People rate in your cities by +100%%[NEWLINE]Your first Golden Age requires only one Great Person, rather than two[NEWLINE]There is no anarchy from civics and religion changes during a Golden Age[NEWLINE]When starting a Custom Single or Multiplayer Game, you may select the "Unrestricted Leaders" option to play any leader with any Civilization[NEWLINE]Selecting the "Choose Religions" option allows you to select which religion you will receive when you discover a religion-founding technology[NEWLINE]Intercontinental Trade Routes, both foreign and domestic, yield one-hundred percent more profit[NEWLINE]You must research the Sailing Technology before you can trade along rivers or coast outside your borders[NEWLINE]Religions no longer grant visibility within a city[NEWLINE]Super Specialists (Great People added to cities as Specialists) now remain in a city even if that city is captured[NEWLINE]You may build up to 5 National Wonders in a One-City Challenge Match[NEWLINE]You may trade for resources you already have[NEWLINE][NEWLINE][BOLD]Trait Changes[\BOLD][NEWLINE]The Expansive Trait offers only +25%% faster production of Workers (previously 50%%)[NEWLINE][LINK=LEADER_AUGUSTUS]Augustus Caesar[\LINK] is an Imperialistic/Industrious leader rather than Organized/Creative[NEWLINE][NEWLINE][BOLD]Promotion Changes[NEWLINE][\BOLD]Air Units now have their own [LINK=CONCEPT_AIR_PROMOTIONS]Promotions[\LINK][NEWLINE]New Promotion - Woodsman III - Heals Units in the Same Tile an Extra 15%%/Turn, +50%% Attack in Jungle, +50%% Attack in Forest[NEWLINE][LINK=PROMOTION_GUERILLA3]Guerilla III[\LINK] now receives a +50%% chance of withdrawal[NEWLINE][LINK=TECH_MILITARY_SCIENCE]Military Science[\LINK] permits access to the Blitz and Commando Promotions[NEWLINE]Gunpowder Units can access the Drill Promotion[NEWLINE][NEWLINE][BOLD]Multiplayer Changes[NEWLINE][\BOLD]Simultaneous Team Turns - Players in multiplayer team games on the same team take their turns simultaneously[NEWLINE][NEWLINE][BOLD]Modding Changes[NEWLINE][\BOLD]You may place cultural borders without the presence of a city on the Worldbuilder screen[NEWLINE]Mods may now have their own GFC themes[NEWLINE]A Modular XML system has been added[NEWLINE][NEWLINE][BOLD]Graphics Changes[\BOLD][NEWLINE]Individual art styles (Middle East, Greco-Roman, etc.) each have their own uniquely styled units. This means that Scouts created by Charlemagne and Scouts created by Suryavarman II will look different, while performing equally[NEWLINE]New styles of roads have been implemented - Roman Roads and Modern Roads + [H1]Modifications des règles de Beyond the Sword[\H1][NEWLINE][NEWLINE][BOLD]Modifications des technologies[\BOLD][NEWLINE]Sélectionnez l'option "Aucun échange de technologie" pour empêcher les joueurs d'échanger des technologies qu'ils n'ont pas recherché eux-mêmes[NEWLINE]Les [LINK=TECH_FIBER_OPTICS]Fibres optiques[\LINK] nécessitent la découverte du [LINK=TECH_LASER]Laser[\LINK] ou de l'[LINK=TECH_COMPUTERS]Informatique[\LINK][NEWLINE]La [LINK=TECH_ROBOTICS]Robotique[\LINK] ne nécessite plus la découverte de la [LINK=TECH_PLASTICS]Plasturgie[\LINK][NEWLINE]L'[LINK=TECH_COMPUTERS]Informatique[\LINK] requiert la [LINK=TECH_PLASTICS]Plasturgie[\LINK][NEWLINE][NEWLINE][BOLD]Modifications des bâtiments[\BOLD][NEWLINE]Les [LINK=BUILDING_AIRPORT]Aéroports[\LINK] confèrent +3 EXP à toutes les unités aériennes et permettent d'abriter quatre unités aériennes supplémentaires dans une ville (jusqu'à 8 au total)[NEWLINE]Le [LINK=BUILDING_PALACE]Palais[\LINK] confère +4 point d'espionnage par tour[NEWLINE]Le [LINK=BUILDING_COURTHOUSE]Tribunal[\LINK] confère +2 points d'espionnage et un espion illustre[NEWLINE]Le [LINK=BUILDING_CASTLE]Château[\LINK] confère +25%% points d'espionnage[NEWLINE]La [LINK=BUILDING_JAIL]Prison[\LINK] confère +4 points d'espionnage, +50%% points d'espionnage et 2 espions illustres[NEWLINE]Le [LINK=BUILDING_LABORATORY]Laboratoire[\LINK] requiert la découverte des [LINK=TECH_SUPERCONDUCTORS]Supraconducteurs[\LINK][NEWLINE]L'[LINK=BUILDING_FACTORY]Usine[\LINK] provoque maintenant des maladies si le joueur a accès au charbon ou au pétrole[NEWLINE]L'[LINK=BUILDING_STABLE]Ecurie[\LINK] est rendue obsolète par l'[LINK=TECH_ADVANCED_FLIGHT]Aviation avancée[\LINK][NEWLINE]Les [LINK=BUILDING_OBELISK]Monuments[\LINK] sont rendus obsolètes par l'[LINK=TECH_ASTRONOMY]Astronomie[\LINK][NEWLINE]L'[LINK=BUILDING_MILITARY_ACADEMY]Académie militaire[\LINK] ne peut être construite qu'après avoir découvert la [LINK=TECH_MILITARY_SCIENCE]Science militaire[\LINK][NEWLINE][NEWLINE][BOLD]Modifications des unités[\BOLD][NEWLINE]Les espions ont subi beaucoup de modifications. Consultez la section [LINK=CONCEPT_ESPIONAGE]Espionnage[\LINK] pour de plus amples informations[NEWLINE]Les unités montées et héliportées bénéficient maintenant d'[LINK=CONCEPT_FLANK_ATTACK]Attaques de flanc[\LINK] contre les armes de siège. Consultez les rubriques de chaque unité pour de plus amples détails[NEWLINE]Le [LINK=UNIT_JAPAN_SAMURAI]Samouraï[\LINK] japonais commence maintenant avec la promotion Exercice I[NEWLINE]La [LINK=UNIT_GREEK_PHALANX]Phalange[\LINK] grecque remplace le [LINK=UNIT_AXEMAN]Soldat avec hache[\LINK][NEWLINE]Le [LINK=UNIT_GRENADIER]Grenadier[\LINK] requiert la découverte de la [LINK=TECH_MILITARY_SCIENCE]Science militaire[\LINK], et non de la [LINK=TECH_CHEMISTRY]Chimie[\LINK][NEWLINE]La [LINK=UNIT_CAVALRY]Cavalerie[\LINK] requiert la découverte du [LINK=TECH_RIFLING]Fusil[\LINK] en plus de la [LINK=TECH_MILITARY_TRADITION]Tradition militaire[\LINK][NEWLINE]L'[LINK=UNIT_SAM_INFANTRY]Infanterie SAM[\LINK]bénéficie d'un bonus de 75%% contre les unités héliportées[NEWLINE]Les unités SAM peuvent bénéficier de la promotion[LINK=CONCEPT_AIR_PROMOTIONS]Interception[\LINK][NEWLINE]La [LINK=UNIT_TRIREME]Trirème[\LINK] requiert la découverte de la [LINK=TECH_METAL_CASTING]Métallurgie[\LINK][NEWLINE]Les [LINK=UNIT_GUNSHIP]Hélicoptères de combat[\LINK] et les [LINK=UNIT_JET_FIGHTER]Chasseurs à réaction[\LINK] ne requièrent que la découverte de l'[LINK=TECH_ADVANCED_FLIGHT]Aviation avancée[\LINK][NEWLINE]L'[LINK=CIVILIZATION_SPAIN]Espagne[\LINK] peut construire des [LINK=UNIT_KNIGHT]Chevaliers[\LINK], tandis que les [LINK=UNIT_SPANISH_CONQUISTADOR]Conquistadors[\LINK] remplacent les [LINK=UNIT_CUIRASSIER]Cuirassiers[\LINK][NEWLINE]Vous ne pouvez abriter que quatre unités aériennes dans une ville à la fois. Si vous disposez d'un [LINK=BUILDING_AIRPORT]Aéroport[\LINK], vous pouvez en abriter huit[NEWLINE]La somme d'expérience requise pour produire des [LINK=UNIT_GREAT_GENERAL]Généraux illustres[\LINK] a été augmentée[NEWLINE]Les bombardements réduisent désormais les défenses d'une ville d'un nombre de dégâts spécifié, et non d'un pourcentage[NEWLINE][NEWLINE][BOLD]Modifications des merveilles[\BOLD][NEWLINE][LINK=BUILDING_SCOTLAND_YARD]Scotland Yard[\LINK] ne peut être construit que par un [LINK=UNIT_GREAT_SPY]Espion illustre[\LINK] et confère +100%% points d'espionnage ainsi que +2 points d'espion illustre[NEWLINE]Le [LINK=BUILDING_PENTAGON]Pentagone[\LINK] confère +2 points d'espion illustre[NEWLINE]La [LINK=BUILDING_GREAT_PALACE]Cité interdite[\LINK] confère +1 point d'espion illustre[NEWLINE]Le [LINK=BUILDING_KREMLIN]Kremlin[\LINK] permet de créer 2 espions et confère +2 points d'espion illustre[NEWLINE][LINK=BUILDING_WEST_POINT]West Point[\LINK] confère +2 points d'espion illustre[NEWLINE][LINK=BUILDING_GREAT_WALL]La Grande muraille[\LINK] confère deux points de personnages illustres (Espion illustre)[NEWLINE]La [LINK=BUILDING_SISTINE_CHAPEL]Chapelle Sixtine[\LINK] confère un bonus culturel de +5 pour chaque bâtiment lié à la religion d'Etat présent dans une ville et peut être construit après avoir recherché la[LINK=TECH_MUSIC]Musique[\LINK][NEWLINE][LINK=BUILDING_NOTRE_DAME]Notre Dame[\LINK] confère un bonus de bonheur de +2 à chaque ville de son continent et peut être construite après avoir recherché l'[LINK=TECH_ENGINEERING]Ingénierie[\LINK][NEWLINE][LINK=BUILDING_PARTHENON]Le Parthénon[\LINK] requiert la découverte de l'[LINK=TECH_AESTHETICS]Esthétique[\LINK][NEWLINE][LINK=BUILDING_HAGIA_SOPHIA]Sainte Sophie[\LINK] requiert la découverte de la [LINK=TECH_THEOLOGY]Théologie[\LINK][NEWLINE][LINK=BUILDING_STONEHENGE]Stonehenge[\LINK] est rendu obsolète par l'[LINK=TECH_ASTRONOMY]Astronomie[\LINK][NEWLINE]Toutes les merveilles nationales confèrent maintenant +1 point de personnage illustre au lieu de +2[NEWLINE][NEWLINE][BOLD]Modifications des doctrines[\BOLD][NEWLINE]L'entretien de l'[LINK=CIVIC_SLAVERY]Esclavage[\LINK] a été modifié et devient moyen[NEWLINE]Avec la découverte du [LINK=CIVIC_MERCANTILISM]Mercantilisme[\LINK], les sociétés commerciales étrangères n'ont plus aucun effet dans vos villes[NEWLINE]L'[LINK=CIVIC_FREE_MARKET]Economie de marché[\LINK] réduit le coût d'entretien des sociétés commerciales de 25%%[NEWLINE]Avec la [LINK=CIVIC_STATE_PROPERTY]Nationalisation[\LINK], les sociétés commerciales n'ont plus d'effet dans vos villes et toutes les villes bénéficient d'un bonus de production de +10%%[NEWLINE]La [LINK=CIVIC_NATIONHOOD]Nationalité[\LINK] confère un bonus de +25%% aux points d'espionnage[NEWLINE]Le [LINK=CIVIC_CASTE_SYSTEM]Système de castes[\LINK] confère un bonus de production dû aux ateliers[NEWLINE]L'[LINK=CIVIC_ENVIRONMENTALISM]Ecologie[\LINK]confère un bonus commercial dû aux [LINK=CONCEPT_BTS_FOREST_PRESERVE]Réserves boisées[\LINK] et aux moulins, mais se fait aux dépens d'une augmentation de 25%% du coût d'entretien des sociétés commerciales[NEWLINE][NEWLINE][BOLD]Modifications des projets[\BOLD][NEWLINE]Vous pouvez voir votre vaisseau spatial ainsi que les pièces que vous avez acquises sur l'écran de victoire[NEWLINE]Le vaisseau spatial peut désormais être lancé sans que son fuselage soit entièrement assemblé, mais chaque pièce manquante augmente considérablement le risque d'échec[NEWLINE]Le [LINK=PROJECT_SS_CASING]fuselage[\LINK] requiert la découverte des [LINK=TECH_COMPOSITES]Matériaux composites[\LINK] au lieu des[LINK=TECH_ROCKETRY]Fusées[\LINK][NEWLINE]Le [LINK=PROJECT_SS_DOCKING_BAY]Module d'amarrage[\LINK] requiert la découverte des [LINK=TECH_SATELLITES]Satellites[\LINK] au lieu de la [LINK=TECH_ROBOTICS]Robotique[\LINK][NEWLINE]L'[LINK=PROJECT_SDI]IDS[\LINK] requiert la découverte du [LINK=TECH_LASER]Laser[\LINK][NEWLINE]L'[LINK=PROJECT_THE_INTERNET]Internet[\LINK] requiert la découverte de l'[LINK=TECH_COMPUTERS]Informatique[\LINK][NEWLINE]Les [LINK=PROJECT_SS_THRUSTERS]Propulseurs[\LINK] requièrent la découvert des [LINK=TECH_SUPERCONDUCTORS]Supraconducteurs[\LINK]Les [NEWLINE]vaisseaux spatiaux bénéficient maintenant d'une arrivée à retardement et peuvent être lancés avec des pièces en double pour augmenter les chances d'arriver plus rapidement. Ils peuvent également être lancés sans l'intégralité des pièces, mais le risque d'échec est alors beaucoup plus élevé.[NEWLINE][NEWLINE][BOLD]Modifications des améliorations[\BOLD][NEWLINE]Les forts ont subi d'importantes modifications. Consultez la section [LINK=CONCEPT_FORT]Forts[\LINK] pour de plus amples détails[NEWLINE]Les chemins de fer peuvent être construits avec du pétrole ou du charbon[NEWLINE][NEWLINE][BOLD]Modifications de l'interface[\BOLD][NEWLINE]Vous pouvez consulter vos quêtes actives sur votre Journal des évènements [CTRL + TAB][NEWLINE]L'écran du conseiller diplomatique a été agrandi[NEWLINE]L'écran de l'Aube de l'humanité a été agrandi[NEWLINE]Les tours écoulés, la recherche par tour et les points d'espionnage par tour sont affichés sur l'interface principal[NEWLINE]Au chapitre de chaque unité de la Civilopédie figure l'unité unique qui vient la remplacer[NEWLINE]Le classement économique a été corrigé sur l'écran de démographie.[NEWLINE]Tout ennemi pénétrant votre territoire clignote en rouge[NEWLINE]En cliquant sur votre score, vous réduisez la liste des dirigeants[NEWLINE]Appuyez sur [CTRL + H] pour sélectionner toutes les unités blessées sur une case spécifique[NEWLINE][NEWLINE][BOLD]Modifications du jeu[\BOLD][NEWLINE]Les parties en vitesse normale durent maintenant 500 tours, mais le passage du temps a été ajusté pour que le jeu se termine tout de même en 2050 ap. J.-C.[NEWLINE]Les [LINK=BUILDING_UNITED_NATIONS]Nations Unies[\LINK] ont été largement remaniées. Consultez la section du [LINK=CONCEPT_APOSTOLIC_PALACE]Palais apostolique[\LINK] pour en savoir plus[NEWLINE]Les Ages d'or augmentent de +100%% le taux de personnages illustres dans vos villes[NEWLINE]Votre premier âge d'or ne requiert qu'un personnage illustre, au lieu de deux[NEWLINE]Pendant un Age d'or, aucune période d'anarchie ne survient en cas de changement de doctrine ou de religion[NEWLINE]Quand vous démarrez une partie personnalisée en mode solo ou multijoueur, vous pouvez sélectionner l'option "Pas de restriction de dirigeants" pour jouer n'importe quel dirigeant avec n'importe quelle civilisation[NEWLINE]En sélectionnant l'option "Choisir religions", vous pouvez sélectionner la religion que vous obtiendrez lorsque vous découvrirez une technologie susceptible de fonder une religion[NEWLINE]Les routes commerciales intercontinentales, nationales et étrangères, confèrent un bénéfice accru de cent pour cent[NEWLINE]Vous devez rechercher la navigation avant de pouvoir commercer le long des rivières ou des côtes[NEWLINE]Les religions ne confèrent plus de visibilité à l'intérieur d'une ville[NEWLINE]Les super spécialistes (personnages illustres incorporés aux villes en tant que spécialistes) demeurent maintenant dans la ville même si cette dernière a été capturée[NEWLINE]Vous ne pouvez construire que 5 merveilles nationales lors d'une partie consistant à Défier une ville[NEWLINE]Vous pouvez échanger des ressources que vous possédez déjà[NEWLINE][BOLD]Modifications des caractéristiques[\BOLD][NEWLINE]Le trait "expansionniste" ne confère plus qu'une augmentation de +25%% de la production des ouvriers (au lieu de 50% précédemment)[NEWLINE][LINK=LEADER_AUGUSTUS]Auguste César[\LINK] est un dirigeant impérialiste/travailleur plutôt qu'organisé/créatif[NEWLINE][NEWLINE][BOLD]Modifications des promotions[NEWLINE][\BOLD]Les unités aériennes ont maintenant leurs propres [LINK=CONCEPT_AIR_PROMOTIONS]Promotions[\LINK][NEWLINE]La nouvelle promotion Forestier III soigne les unités présentes dans la même case de +15%%/tour, confère un bonus d'attaque de +50%% dans la jungle ainsi que dans la forêt.[NEWLINE]La promotion Guérilla III bénéficie désormais de 50%% de chances de fuite supplémentaires[NEWLINE][LINK=TECH_MILITARY_SCIENCE]La Science militaire[\LINK] permet d'accéder aux promotions Blitz et Commando[NEWLINE]Les unités dotées d'armes à feu peuvent accéder à la promotion Exercice[NEWLINE][NEWLINE][BOLD]Modifications du mode multijoueur[NEWLINE][\BOLD]Tours d'équipes simultanés - Les joueurs d'une équipe engagée dans une partie en mode multijoueur jouent leurs tours simultanément[NEWLINE][NEWLINE][BOLD]Modifications des mods[NEWLINE][\BOLD]Dans l'éditeur de mondes, vous pouvez désormais placer des frontières culturelles sans la présence d'une ville[NEWLINE]Les mods peuvent maintenant avoir leurs propres thèmes GFC[NEWLINE]Un système modulaire XML a été ajouté[NEWLINE][NEWLINE][BOLD]Modifications des graphismes[\BOLD][NEWLINE]Chaque courant artistique (oriental, gréco-romain, etc.) confère un style différent aux unités de la civilisation concernée. Ceci signifie que les éclaireurs créés par Charlemagne et ceux créés par Suryavarman II auront un aspect différent alors que leurs performances demeurent parfaitement égales[NEWLINE]De nouveaux styles de routes ont été incorporés : les routes romaines et les routes modernes. + [H1]Regeländerungen in Beyond the Sword[\H1][NEWLINE][NEWLINE][BOLD]Technologie-Änderungen[\BOLD][NEWLINE]Durch Auswahl der Option "Kein Technologieaustausch" wird es für die Spieler unmöglich, Technologien auszutauschen, die sie noch nicht selbst erforscht haben[NEWLINE][LINK=TECH_FIBER_OPTICS]Glasfasertechnologie[\LINK] erfordert die Technologie [LINK=TECH_LASER]Laser[\LINK] oder die [LINK=TECH_COMPUTERS]Computertechnologie[\LINK][NEWLINE][LINK=TECH_ROBOTICS]Robotertechnik[\LINK] erfordert [LINK=TECH_PLASTICS]Plastik[\LINK] nicht mehr direkt[NEWLINE][LINK=TECH_COMPUTERS]Computertechnologie[\LINK] erfordert [LINK=TECH_PLASTICS]Plastik[\LINK][NEWLINE][NEWLINE][BOLD]Gebäude-Änderungen[\BOLD][NEWLINE][LINK=BUILDING_AIRPORT]Flughäfen[\LINK] gewähren +3 EP auf alle Lufteinheiten und ermöglichen die Stationierung 4 zusätzlicher Lufteinheiten in einer Stadt (insgesamt acht)[NEWLINE]Der [LINK=BUILDING_PALACE]Palast[\LINK] gewährt +4 Spionagepunkt pro Runde[NEWLINE]Das [LINK=BUILDING_COURTHOUSE]Gerichtsgebäude[\LINK] gewährt +2 Spionagepunkte und 1 Spion-Spezialist[NEWLINE]Das [LINK=BUILDING_CASTLE]Schloss[\LINK] gewährt +25%% Spionagepunkte[NEWLINE]Das [LINK=BUILDING_JAIL]Gefängnis[\LINK] gewährt +4 Spionagepunkte, +50%% Spionagepunkte und 2 Spion-Spezialisten[NEWLINE]Das [LINK=BUILDING_LABORATORY]Labor[\LINK] gewährt die Technologie [LINK=TECH_SUPERCONDUCTORS]Supraleiter[\LINK][NEWLINE]Die [LINK=BUILDING_FACTORY]Fabrik[\LINK] verursacht nun Krankheit mit Zugang zu Kohle oder Öl[NEWLINE]Das Gebäude [LINK=BUILDING_STABLE]Stall[\LINK] veraltet durch die Technologie [LINK=TECH_ADVANCED_FLIGHT]Fortgeschrittene Luftfahrt[\LINK][NEWLINE][LINK=BUILDING_OBELISK]Monumente[\LINK] veralten durch die Technologie [LINK=TECH_ASTRONOMY]Astronomie[\LINK][NEWLINE]Die [LINK=BUILDING_MILITARY_ACADEMY]Militärakademie[\LINK] kann erst nach der Erforschung der Technologie [LINK=TECH_MILITARY_SCIENCE]Militärwissenschaft[\LINK] erbaut werden[NEWLINE][NEWLINE][BOLD]Einheiten-Änderungen[\BOLD][NEWLINE]Spione wurden deutlich verändert. Weitere Informationen finden Sie unter [LINK=CONCEPT_ESPIONAGE]Spionage[\LINK][NEWLINE]Berittene Einheiten und Hubschrauber erhalten nun [LINK=CONCEPT_FLANK_ATTACK]Flankenangriffe[\LINK] gegen Belagerungswaffen. Weitere Informationen finden Sie unter den jeweiligen Einträgen[NEWLINE]Die japanischen [LINK=UNIT_JAPAN_SAMURAI]Samurai[\LINK] beginnen nun mit der Beförderung Drill I[NEWLINE]Die griechische Einheit [LINK=UNIT_GREEK_PHALANX]Phalanx[\LINK] ersetzt den [LINK=UNIT_AXEMAN]Axtkämpfer[\LINK][NEWLINE]Die Einheit [LINK=UNIT_GRENADIER]Grenadier[\LINK] erfordert [LINK=TECH_MILITARY_SCIENCE]Militärwissenschaft[\LINK], nicht [LINK=TECH_CHEMISTRY]Chemie[\LINK][NEWLINE]Die Einheit [LINK=UNIT_CAVALRY]Kavallerie[\LINK] erfordert die Technologie [LINK=TECH_RIFLING]Drall[\LINK] zusätzlich zur Technologie [LINK=TECH_MILITARY_TRADITION]Militärwesen[\LINK][NEWLINE]Die Einheit [LINK=UNIT_SAM_INFANTRY]SAM-Infanterie[\LINK] erhält einen Bonus von 75%% gegen Hubschrauber[NEWLINE]SAM-Einheiten können [LINK=CONCEPT_AIR_PROMOTIONS]Abfangen[\LINK]-Beförderungen erhalten[NEWLINE]Die Einheit [LINK=UNIT_TRIREME]Triere[\LINK] erfordert die Technologie [LINK=TECH_METAL_CASTING]Metallguss[\LINK][NEWLINE]Die Einheiten [LINK=UNIT_GUNSHIP]Kampfhubschrauber[\LINK] und [LINK=UNIT_JET_FIGHTER]Düsenjäger[\LINK] erfordern nur die Technologie [LINK=TECH_ADVANCED_FLIGHT]Fortgeschrittene Luftfahrt[\LINK][NEWLINE][LINK=CIVILIZATION_SPAIN]Spanien[\LINK] kann [LINK=UNIT_KNIGHT]Ritter[\LINK] errichten, wenn der [LINK=UNIT_SPANISH_CONQUISTADOR]Konquistador[\LINK] den [LINK=UNIT_CUIRASSIER]Kürassier[\LINK] ersetzt[NEWLINE]Sie können nur vier Lufteinheiten gleichzeitig in einer Stadt stationieren. Mit dem Gebäude [LINK=BUILDING_AIRPORT]Flughafen[\LINK] können Sie acht Lufteinheiten stationieren[NEWLINE]Die Erfahrung, die zur Produktion aufeinanderfolgender [LINK=UNIT_GREAT_GENERAL]Großer Generäle[\LINK] benötigt wird, wurde erhöht[NEWLINE]Bombardierung reduziert nun die Stadtverteidigung um einen fixen Wert anstelle eines Prozentwerts[NEWLINE][NEWLINE][BOLD]Wunder-Änderungen[\BOLD][NEWLINE][LINK=BUILDING_SCOTLAND_YARD]Scotland Yard[\LINK] kann nur von einem [LINK=UNIT_GREAT_SPY]Großen Spion[\LINK] errichtet werden und gewährt +100%% Spionage und +2 Großer Spion-Punkte[NEWLINE]Das [LINK=BUILDING_PENTAGON]Pentagon[\LINK] gewährt +2 Großer Spion-Punkte[NEWLINE]Die [LINK=BUILDING_GREAT_PALACE]Verbotene Stadt[\LINK] gewährt +1 Großer Spion-Punkt[NEWLINE]Der [LINK=BUILDING_KREMLIN]Kreml[\LINK] ermöglicht die Erschaffung von 2 Spion-Spezialisten und gewährt +2 Großer Spion Punkte[NEWLINE][LINK=BUILDING_WEST_POINT]West Point[\LINK] gewährt +2 Großer Spion-Punkte[NEWLINE][LINK=BUILDING_GREAT_WALL]Die Große Mauer[\LINK] gewährt zwei Große Persönlichkeit-Punkte (Großer Spion)[NEWLINE]Die [LINK=BUILDING_SISTINE_CHAPEL]Sixtinische Kapelle[\LINK] gewährt +5 auf Kultur für jedes Staatsreligionsgebäude in einer Stadt und kann nach Erforschung der Technologie [LINK=TECH_MUSIC]Musik[\LINK] errichtet werden[NEWLINE][LINK=BUILDING_NOTRE_DAME]Notre Dame[\LINK] gewährt jeder Stadt, die sich auf demselben Kontinent befindet, + 2 Zufriedenheit und kann nach Erforschung der Technologie [LINK=TECH_ENGINEERING]Maschinenbau[\LINK] errichtet werden[NEWLINE][LINK=BUILDING_PARTHENON]Der Parthenon[\LINK] erfordert die Technologie [LINK=TECH_AESTHETICS]Ästhetik[\LINK][NEWLINE]Die [LINK=BUILDING_HAGIA_SOPHIA]Hagia Sophia[\LINK] erfordert die Technologie [LINK=TECH_THEOLOGY]Theologie[\LINK][NEWLINE][LINK=BUILDING_STONEHENGE]Stonehenge[\LINK] veraltet mit der Technologie [LINK=TECH_ASTRONOMY]Astronomie[\LINK][NEWLINE]Alle Nationalen Wunder gewähren nun +1 Große Persönlichkeit-Punkte anstelle von +2[NEWLINE][NEWLINE][BOLD]Staatsformen-Änderungen[\BOLD][NEWLINE]Der Unterhalt für [LINK=CIVIC_SLAVERY]Sklaverei[\LINK] wurde auf Mittel erhöht[NEWLINE][LINK=CIVIC_MERCANTILISM]Merkantilismus[\LINK] bewirkt, dass Ausländische Kapitalgesellschaften keine Auswirkungen auf Ihre Städte haben[NEWLINE][LINK=CIVIC_FREE_MARKET]Freie Marktwirtschaft[\LINK] reduziert den Unterhalt für Kapitalgesellschaften um 25%%[NEWLINE][LINK=CIVIC_STATE_PROPERTY]Staatseigentum[\LINK] bewirkt, dass Kapitalgesellschaften keine Auswirkungen auf Ihre Städte haben, und gewährt +10%% Produktionsbonus in allen Städten[NEWLINE][LINK=CIVIC_NATIONHOOD]Nationale Selbstständigkeit[\LINK] gewährt +25%% Bonus auf Spionagepunkte[NEWLINE]Das [LINK=CIVIC_CASTE_SYSTEM]Kastensystem[\LINK] gewährt einen Produktionsbonus durch Werkstätten[NEWLINE][LINK=CIVIC_ENVIRONMENTALISM]Umweltschutz[\LINK] gewährt einen Wirtschaftsbonus durch [LINK=CONCEPT_BTS_FOREST_PRESERVE]Aufforstungsgebiete[\LINK] und Windmühlen, allerdings zulasten eines 25%%-igen Anstiegs des Unterhalts für Kapitalgesellschaften[NEWLINE][NEWLINE][BOLD]Projekt-Änderungen[\BOLD][NEWLINE]Sie können Ihr Raumschiff und die fertig gestellten Teile auf dem Sieg-Bildschirm sehen[NEWLINE]Ein Raumschiff kann nun gestartet werden, bevor die Ummantelung fertiggestellt wurde, aber jedes fehlende Teil erhöht das Risiko eines Ausfalls deutlich[NEWLINE][LINK=PROJECT_SS_CASING]RS-Ummantelung[\LINK] erfordert die Technologie [LINK=TECH_COMPOSITES]Verbundstoffe[\LINK] anstelle von [LINK=TECH_ROCKETRY]Raketentechnik[\LINK][NEWLINE][LINK=PROJECT_SS_DOCKING_BAY]RS-Andockbucht[\LINK] erfordert [LINK=TECH_SATELLITES]Satellitentechnologie[\LINK] anstelle von [LINK=TECH_ROBOTICS]Robotertechnik[\LINK][NEWLINE][LINK=PROJECT_SDI]SDI[\LINK] erfordert die Technologie [LINK=TECH_LASER]Laser[\LINK][NEWLINE][LINK=PROJECT_THE_INTERNET]Das Internet[\LINK] erfordert die [LINK=TECH_COMPUTERS]Computertechnologie[\LINK][NEWLINE]Das [LINK=PROJECT_SS_THRUSTERS]RS-Triebwerk[\LINK] erfordert die Technologie [LINK=TECH_SUPERCONDUCTORS]Supraleiter[\LINK][NEWLINE]Raumschiffe haben nun eine verzögerte Ankunft und können mit zusätzlichen Systemen gestartet werden, um die Erfolgschance zu erhöhen oder die Ankunft zu beschleunigen. Sie können auch gestartet werden, wenn bestimmte Systeme fehlen, aber das erhöht das Risiko eines Ausfalls[NEWLINE][NEWLINE][BOLD]Modernisierungs-Änderungen[\BOLD][NEWLINE]Festungen wurden deutlich verändert. Eine detaillierte Beschreibung dieser Änderungen finden Sie im Abschnitt [LINK=CONCEPT_FORT]Festungen[\LINK][NEWLINE]Eisenbahnen können mit Öl oder Kohle errichtet werden[NEWLINE][NEWLINE][BOLD]Interface-Änderungen[\BOLD][NEWLINE]Sie können Ihre aktiven Quests im Log-Bildschirm [STRG + TAB] einsehen[NEWLINE]Der Auslandsberater-Bildschirm wurde erweitert[NEWLINE]Der Dawn of Man-Bildschirm wurde erweitert[NEWLINE]Vergangene Runden, Forschung pro Runde und Spionagepunkte pro Runde werden im Hauptbildschirm angezeigt[NEWLINE]Einheiten zeigen in der Zivilopädie alle Spezialeinheiten an, die sie ersetzen[NEWLINE]Der Demografien-Bildschirm zeigt nun die korrekte wirtschaftliche Bewertung[NEWLINE]Gegner, die Ihr Gebiet betreten, leuchten rot[NEWLINE]Wenn Sie auf Ihren eigenen Punktestand klicken, wird die Liste der Staatsoberhäupter minimiert[NEWLINE]Durch Drücken von [STRG + H] werden alle verletzten Einheiten auf einem bestimmten Geländefeld ausgewählt[NEWLINE][NEWLINE][BOLD]Änderungen im Spielablauf[\BOLD][NEWLINE]Ein Spiel bei Normalgeschwindigkeit dauert nun 500 Runden, aber die Zeitdauer wurde angepasst, so dass das Spiel immer noch 2050 n. Chr. endet[NEWLINE]Die [LINK=BUILDING_UNITED_NATIONS]Vereinten Nationen[\LINK] wurden deutlich erweitert. Weitere Informationen dazu finden Sie im Abschnitt [LINK=CONCEPT_APOSTOLIC_PALACE]Apostolischer Palast[\LINK][NEWLINE]Goldene Zeitalter erhöhen die Häufigkeit Großer Persönlichkeiten in Ihren Städten um +100%%[NEWLINE]Ihr erstes Goldenes Zeitalter erfordert nur eine Große Persönlichkeit statt zwei[NEWLINE]Änderungen an Staatsform und Religion während eines Goldenen Zeitalters führen nicht zu Anarchie[NEWLINE]Wenn Sie ein Eigenes Einzelspieler- oder Multiplayer-Spiel starten, können Sie die Option "Beliebige Staatsoberhäupter" wählen und so in die Rolle eines beliebigen Staatsoberhaupts in einer beliebigen Zivilisation schlüpfen[NEWLINE]Mit der Option "Religionen wählen" können Sie auswählen, welche Religion Sie erhalten, wenn Sie eine religionsbegründende Technologie entdecken[NEWLINE]Interkontinentale Handelsrouten, sowohl ausländische als auch inländische, bringen 100%% mehr Gewinn[NEWLINE]Sie müssen die Technologie Segeln erforschen, bevor Sie entlang von Flüssen oder Küsten Handel betreiben können[NEWLINE]Religionen gewähren nun keine Sicht mehr in einer Stadt[NEWLINE]Super-Spezialisten (Große Persönlichkeiten, die Städten als Spezialisten zugewiesen werden) bleiben nun in einer Stadt, auch wenn diese Stadt erobert wird[NEWLINE]Sie können in einem Einzelstadt-Wettkampf nur noch 5 Nationale Wunder errichten[NEWLINE]Sie können Ressourcen kaufen, die Sie bereits haben[NEWLINE][NEWLINE][BOLD]Eigenschafts-Änderungen[\BOLD][NEWLINE]Die Eigenschaft Expansiv beschleunigt die Produktion von Bautrupps nur noch um +25%% (vorher 50%%)[NEWLINE][LINK=LEADER_AUGUSTUS]Augustus Cäsar[\LINK] ist eher ein Imperialistisches/Industrielles Staatsoberhaupt als Organisiert/Kreativ[NEWLINE][NEWLINE][BOLD]Beförderungs-Änderungen[NEWLINE][\BOLD]Lufteinheiten haben nun eigene [LINK=CONCEPT_AIR_PROMOTIONS]Beförderungen[\LINK][NEWLINE]Neue Beförderung - Waldkampf III - Heilt Einheiten auf demselben Geländefeld um zusätzlich 15%%/Runde, +50%% Angriff im Dschungel, +50%% Angriff im Wald[NEWLINE]Guerilla III gewährt nun +50%% Rückzugschance[NEWLINE][LINK=TECH_MILITARY_SCIENCE]Militärwissenschaft[\LINK] ermöglicht nun die Beförderungen Blitzkrieg und Kommando[NEWLINE]Schießpulver-Einheiten haben Zugang zur Drill-Beförderung[NEWLINE][NEWLINE][BOLD]Multiplayer-Änderungen[NEWLINE][\BOLD]Team-Simultanrunden - Spieler desselben Teams in Multiplayer-Teamspielen absolvieren ihre Runden gleichzeitig[NEWLINE][NEWLINE][BOLD]Mod-Änderungen[NEWLINE][\BOLD]Sie können kulturelle Grenzen ohne Stadt auf dem Weltenbauer-Bildschirm errichten[NEWLINE]Mods können nun eigene GFC-Themen haben[NEWLINE]Ein modulares XML-System wurde hinzugefügt[NEWLINE][NEWLINE][BOLD]Grafik-Änderungen[\BOLD][NEWLINE]Die verschiedenen Kunstrichtungen (Mittlerer Osten, Griechisch-Römisch, etc.) haben eigens entworfene Einheiten. Das heißt, Späher von Karl dem Großen und Späher von Suryavarman II. sehen unterschiedlich aus, haben aber dieselben Eigenschaften[NEWLINE]Neue Straßenarten wurden eingebaut - Römische Straßen und Moderne Straßen + [H1]Cambiamenti delle regole di Beyond the Sword[\H1][NEWLINE][NEWLINE][BOLD]Cambiamenti nella tecnologia[\BOLD][NEWLINE]Selezionando l'opzione "Nessuna vendita di tecnologie" sarà impossibile per i giocatori scambiare tecnologie che non hanno ricercato per conto proprio[NEWLINE]Le [LINK=TECH_FIBER_OPTICS]Fibre ottiche[\LINK] richiedono [LINK=TECH_LASER]Laser[\LINK] o [LINK=TECH_COMPUTERS]Computer[\LINK][NEWLINE]La [LINK=TECH_ROBOTICS]Robotica[\LINK] non richiede più [LINK=TECH_PLASTICS]Plastica[\LINK][NEWLINE]I [LINK=TECH_COMPUTERS]Computer[\LINK] richiedono [LINK=TECH_PLASTICS]Plastica[\LINK][NEWLINE][NEWLINE][BOLD]Cambiamenti degli edifici[\BOLD][NEWLINE]Gli [LINK=BUILDING_AIRPORT]Aeroporti[\LINK] forniscono +3 XP a tutte le unità aeree e permettono di ospitare quattro unità extra nella città in cui sono costruiti (per un totale di otto)[NEWLINE]Il [LINK=BUILDING_PALACE]Palazzo[\LINK] fornisce +4 Punti spionaggio per turno[NEWLINE]Il [LINK=BUILDING_COURTHOUSE]Palazzo di giustizia[\LINK] fornisce +2 Punti spionaggio e 1 Spia specialista[NEWLINE]Il [LINK=BUILDING_CASTLE]Castello[\LINK] fornisce il +25%% di Punti spionaggio[NEWLINE]La [LINK=BUILDING_JAIL]Prigione[\LINK] fornisce +4 Punti spionaggio, +50%% di Punti spionaggio e 2 Spie specialiste[NEWLINE]Il [LINK=BUILDING_LABORATORY]Laboratorio[\LINK] richiede [LINK=TECH_SUPERCONDUCTORS]Superconduttori[\LINK][NEWLINE]Le [LINK=BUILDING_FACTORY]Fabbriche[\LINK] che hanno accesso a carbone o petrolio adesso causano malessere tra la popolazione[NEWLINE]La [LINK=BUILDING_STABLE]Stalla[\LINK] è resa obsoleta da [LINK=TECH_ADVANCED_FLIGHT]Volo avanzato[\LINK][NEWLINE]I [LINK=BUILDING_OBELISK]Monumenti[\LINK] sono resi obsoleti da [LINK=TECH_ASTRONOMY]Astronomia[\LINK][NEWLINE]L'[LINK=BUILDING_MILITARY_ACADEMY]Accademia militare[\LINK] può essere costruita solo dopo aver ricercato [LINK=TECH_MILITARY_SCIENCE]Scienza militare[\LINK][NEWLINE][NEWLINE][BOLD]Cambiamenti delle unità[\BOLD][NEWLINE]Le spie sono state modificate in maniera sostanziale. Per ulteriori informazioni, consulta la voce [LINK=CONCEPT_ESPIONAGE]Spionaggio[\LINK][NEWLINE]Le unità montate e gli Elicotteri ricevono [LINK=CONCEPT_FLANK_ATTACK]Attacchi ai fianchi[\LINK] contro le Armi d'assedio. Per ulteriori dettagli consulta le singole voci[NEWLINE]Il [LINK=UNIT_JAPAN_SAMURAI]Samurai[\LINK] giapponese ora comincia con la Promozione Addestramento I[NEWLINE]La [LINK=UNIT_GREEK_PHALANX]Falange[\LINK] greca sostituisce il [LINK=UNIT_AXEMAN]Guerriero con ascia[\LINK].[NEWLINE]Il [LINK=UNIT_GRENADIER]Granatiere[\LINK] richiede [LINK=TECH_MILITARY_SCIENCE]Scienza militare[\LINK], non [LINK=TECH_CHEMISTRY]Chimica[\LINK][NEWLINE]La [LINK=UNIT_CAVALRY]Cavalleria[\LINK] richiede [LINK=TECH_RIFLING]Rigatura delle canne[\LINK] oltre a [LINK=TECH_MILITARY_TRADITION]Tradizione militare[\LINK][NEWLINE]La [LINK=UNIT_SAM_INFANTRY]Fanteria con missili terra-aria[\LINK] riceve un bonus del 75%% contro le unità Elicotteri[NEWLINE]Le unità con missili terra-aria possono ricevere le promozioni [LINK=CONCEPT_AIR_PROMOTIONS]Intercettazione[\LINK][NEWLINE]Il [LINK=UNIT_TRIREME]Trireme[\LINK] richiede [LINK=TECH_METAL_CASTING]Fusione del metallo[\LINK][NEWLINE]Gli [LINK=UNIT_GUNSHIP]Elicotteri da guerra[\LINK] e i [LINK=UNIT_JET_FIGHTER]Jet da combattimento[\LINK] richiedono solo [LINK=TECH_ADVANCED_FLIGHT]Volo avanzato[\LINK][NEWLINE]La [LINK=CIVILIZATION_SPAIN]Spagna[\LINK] può costruire [LINK=UNIT_KNIGHT]Cavalieri[\LINK], dato che il [LINK=UNIT_SPANISH_CONQUISTADOR]Conquistador[\LINK] sostituisce il [LINK=UNIT_CUIRASSIER]Corazziere[\LINK][NEWLINE]Una città può ospitare solo quattro unità aeree. Con un [LINK=BUILDING_AIRPORT]Aeroporto[\LINK] puoi ospitarne fino a otto[NEWLINE]È stata aumentata la quantità di esperienza necessaria per produrre altri [LINK=UNIT_GREAT_GENERAL]Grandi Generali[\LINK][NEWLINE]I bombardamenti riducono le difese cittadine di un valore prefissato, e non di una percentuale[NEWLINE][NEWLINE][BOLD]Cambiamenti delle meraviglie[\BOLD][NEWLINE][LINK=BUILDING_SCOTLAND_YARD]Scotland Yard[\LINK] può essere costruita solo da una [LINK=UNIT_GREAT_SPY]Grande Spia[\LINK], e fornisce +100%% di spionaggio e +2 punti Grande Spia[NEWLINE]Il [LINK=BUILDING_PENTAGON]Pentagono[\LINK] fornisce +2 punti Grande Spia[NEWLINE]Il [LINK=BUILDING_GREAT_PALACE]Palazzo Proibito[\LINK] fornisce +1 punto Grande Spia[NEWLINE]Il [LINK=BUILDING_KREMLIN]Cremlino[\LINK] permette la creazione di 2 spie specialiste e fornisce +2 punti Grande Spia[NEWLINE][LINK=BUILDING_WEST_POINT]West Point[\LINK] fornisce +2 punti Grande Spia[NEWLINE][LINK=BUILDING_GREAT_WALL]La Grande Muraglia[\LINK] fornisce due punti Grandi Personaggi (Grande Spia)[NEWLINE]La [LINK=BUILDING_SISTINE_CHAPEL]Cappella Sistina[\LINK] fornisce +5 cultura per ogni edificio della religione di stato in una città, e può essere costruita dopo aver ricercato [LINK=TECH_MUSIC]Musica[\LINK][NEWLINE][LINK=BUILDING_NOTRE_DAME]Notre Dame[\LINK] fornisce + 2 felicità a ogni città che si trova sul suo continente, e può essere costruita dopo aver ricercato [LINK=TECH_ENGINEERING]Ingegneria[\LINK][NEWLINE]Il [LINK=BUILDING_PARTHENON]Partenone[\LINK] richiede l'[LINK=TECH_AESTHETICS]Estetica[\LINK][NEWLINE][LINK=BUILDING_HAGIA_SOPHIA]Santa Sofia[\LINK] richiede [LINK=TECH_THEOLOGY]Teologia[\LINK][NEWLINE][LINK=BUILDING_STONEHENGE]Stonehenge[\LINK] diventa obsoleto con [LINK=TECH_ASTRONOMY]Astronomia[\LINK][NEWLINE]Tutte le meraviglie nazionali ora forniscono +1 punto Grande Personaggio invece di +2[NEWLINE][NEWLINE][BOLD]Cambiamenti alle forme di governo[\BOLD][NEWLINE]Il mantenimento dello [LINK=CIVIC_SLAVERY]Schiavismo[\LINK] è stato cambiato in Medio[NEWLINE]Il [LINK=CIVIC_MERCANTILISM]Mercantilismo[\LINK] impedisce alle corporazioni straniere di avere effetti nelle tue città[NEWLINE]Il [LINK=CIVIC_FREE_MARKET]Libero mercato[\LINK] riduce il costo di manutenzione delle Corporazioni del 25%%[NEWLINE]La [LINK=CIVIC_STATE_PROPERTY]Proprietà statale[\LINK] impedisce alle corporazioni di avere effetti nelle tue città e fornisce un bonus del +10%% nella produzione in tutte le città[NEWLINE]L'[LINK=CIVIC_NATIONHOOD]Identità nazionale[\LINK] fornisce +25%% di bonus ai Punti spionaggio[NEWLINE]Il [LINK=CIVIC_CASTE_SYSTEM]Sistema a caste[\LINK] fornisce un bonus di produzione dalle botteghe[NEWLINE]L'[LINK=CIVIC_ENVIRONMENTALISM]Ambientalismo[\LINK] fornisce un bonus nel commercio dalle [LINK=CONCEPT_BTS_FOREST_PRESERVE]Riserve forestali[\LINK] e mulini a vento, contro un 25%% di aumento nei costi di mantenimento delle Corporazioni[NEWLINE][NEWLINE][BOLD]Cambiamenti del progetto[\BOLD][NEWLINE]Ora puoi vedere la tua Astronave e le parti completate nella Schermata della vittoria[NEWLINE]È possibile lanciare un'astronave senza aver interamente completato lo scafo, ma ogni pezzo mancante aumenta notevolmente il rischio di fallimento[NEWLINE]Lo [LINK=PROJECT_SS_CASING]Scafo dell'astronave[\LINK] richiede [LINK=TECH_COMPOSITES]Composti[\LINK] al posto di [LINK=TECH_ROCKETRY]Missilistica[\LINK][NEWLINE]Il [LINK=PROJECT_SS_DOCKING_BAY]Modulo d'attracco dell'astronave[\LINK] richiede [LINK=TECH_SATELLITES]Satelliti[\LINK] invece di [LINK=TECH_ROBOTICS]Robotica[\LINK][NEWLINE][LINK=PROJECT_SDI]SDI[\LINK] richiede [LINK=TECH_LASER]Laser[\LINK][NEWLINE][LINK=PROJECT_THE_INTERNET]Internet[\LINK] richiede [LINK=TECH_COMPUTERS]Computer[\LINK][NEWLINE]I [LINK=PROJECT_SS_THRUSTERS]Propulsori dell'astronave[\LINK] richiedono [LINK=TECH_SUPERCONDUCTORS]Superconduttori[\LINK][NEWLINE]Le astronavi hanno un tempo di arrivo più lungo, e possono essere lanciate con sistemi ridondanti per aumentare le possibilità di successo o per ridurre il tempo di arrivo. Possono anche essere lanciate senza alcuni componenti, aumentando così il rischio di fallimento[NEWLINE][NEWLINE][BOLD]Cambiamenti dei miglioramenti[\BOLD][NEWLINE]I Forti sono cambiati in maniera significativa. Per una spiegazione più approfondita, consulta la sezione [LINK=CONCEPT_FORT]Forti[\LINK][NEWLINE]Le ferrovie possono essere costruite con petrolio o carbone[NEWLINE][NEWLINE][BOLD]Cambiamenti dell'interfaccia[\BOLD][NEWLINE]È possibile vedere le missioni attive nel Registro eventi [CTRL + TAB][NEWLINE]La schermata del Consigliere estero è stata migliorata[NEWLINE]La schermata Alba dell'umanità è stata ampliata[NEWLINE]Turni trascorsi, ricerca per turno e punti spionaggio per turno sono ora visualizzati nell'interfaccia principale[NEWLINE]Le unità della Civilopedia mostrano qualunque unità unica che le sostituisce[NEWLINE]La schermata della demografia mostra ora la classificazione economica corretta[NEWLINE]I nemici che entrano nel tuo territorio sono indicati in rosso[NEWLINE]Cliccando sul tuo punteggio viene minimizzato l'elenco dei leader[NEWLINE]Premendo [CTRL + H] vengono selezionate tutte le unità ferite di una specifica casella[NEWLINE][NEWLINE][BOLD]Cambiamenti di gioco[\BOLD][NEWLINE]Le partite a velocità normale durano ora 500 turni, ma lo scorrere del tempo è stato corretto, in modo che la partita termini comunque nel 2050 d.C.[NEWLINE]Le [LINK=BUILDING_UNITED_NATIONS]Nazioni Unite[\LINK] sono state notevolmente ampliate. Per ulteriori dettagli consulta la sezione [LINK=CONCEPT_APOSTOLIC_PALACE]Palazzo Apostolico[\LINK][NEWLINE]Le Età dell'oro aumentano del +100%% il tasso di Grandi Personaggi nelle tue città[NEWLINE]La tua prima Età dell'oro richiede un solo Grande Personaggio, e non due[NEWLINE]Durante l'Età dell'Oro non c'è anarchia quando si adotta una nuova forma di governo o una religione.[NEWLINE]Quando si inizia una partita personalizzata o multigiocatore, puoi selezionare l'opzione "Leader senza limitazioni" per giocare con qualsiasi leader di qualunque civiltà[NEWLINE]Selezionare l'opzione "Scegli religioni" ti permette di selezionare la religione che riceverai quando scopri una tecnologia che permette di fondare una religione[NEWLINE]Le rotte commerciali intercontinentali, sia estere che locali, aumentano i profitti del cento per cento[NEWLINE]Prima di poter commerciare lungo i fiumi o le coste fuori dai tuoi confini dovrai ricercare la tecnologia Navigazione[NEWLINE]Le religioni non forniscono più visibilità all'interno di una città[NEWLINE]I super specialisti (Grandi personaggi aggiunti alle città come Specialisti) rimangono in quella città anche se viene conquistata[NEWLINE]Nella Sfida con una singola città puoi costruire fino a 5 Meraviglie Nazionali[NEWLINE]Puoi effettuare scambi per risorse che già possiedi[NEWLINE][NEWLINE][BOLD]Cambiamenti delle caratteristiche[\BOLD][NEWLINE]La caratteristica Espansionista offre solo il +25%% di velocità in più nella produzione di Lavoratori (prima era il 50%%)[NEWLINE][LINK=LEADER_AUGUSTUS]Cesare Augusto[\LINK] è un leader Imperialista/Industrioso più che Organizzato/Creativo[NEWLINE][NEWLINE][BOLD]Cambiamenti delle promozioni[NEWLINE][\BOLD]Le unità aeree ora hanno [LINK=CONCEPT_AIR_PROMOTIONS]Promozioni[\LINK] proprie[NEWLINE]Nuova promozione - Taglialegna III - Cura le unità nella medesima casella di un ulteriore 15%%/turno, +50%% di attacco nella giungla, +50%% di attacco nella foresta[NEWLINE][LINK=PROMOTION_GUERILLA3]Guerriglia III[\LINK] riceve ora un +50%% di possibilità di ritirata[NEWLINE]La [LINK=TECH_MILITARY_SCIENCE]Scienza militare[\LINK] permette di accedere alle Promozioni Incursione e Commando[NEWLINE]Le Unità con armi da fuoco possono ottenere la Promozione Addestramento[NEWLINE][NEWLINE][BOLD]Cambiamenti alla modalità multigiocatore[NEWLINE][\BOLD]Turni di squadra contemporanei - I giocatori della stessa squadra giocano i loro turni simultaneamente[NEWLINE][NEWLINE][BOLD]Modifiche del modding[NEWLINE][\BOLD]Nella schermata dell'editor puoi disporre i confini culturali senza la presenza di una città[NEWLINE]I mod possono avere i propri temi[NEWLINE]È stato inserito un sistema modulare XML[NEWLINE][NEWLINE][BOLD]Cambiamenti grafici[\BOLD][NEWLINE]Gli stili artistici individuali (Medio Oriente, Greco-Romano, ecc.) hanno le proprie unità caratterizzate anche dal punto di vista grafico. Questo significa che i Ricognitori creati da Carlo Magno e quelli creati da Suryavarman II saranno diversi nell'aspetto, seppur identici nel comportamento[NEWLINE]Sono stati inseriti nuovi stili delle strade - le Strade romane e quelle moderne + [H1]Cambios en las reglas de "Beyond The Sword"[\H1][NEWLINE][NEWLINE][BOLD]Cambios en las tecnologías[\BOLD][NEWLINE]Al seleccionar la opción "Sin intermediación con tecnología" se impide a los jugadores intercambiar tecnologías que no hayan investigado por sí mismos.[NEWLINE]La [LINK=TECH_FIBER_OPTICS]Fibra óptica[\LINK] requiere [LINK=TECH_LASER]Láser[\LINK] u [LINK=TECH_COMPUTERS]Ordenadores[\LINK][NEWLINE]La [LINK=TECH_ROBOTICS]Robótica[\LINK] ya no requiere directamente [LINK=TECH_PLASTICS]Plástico[\LINK].[NEWLINE]Los [LINK=TECH_COMPUTERS]Ordenadores[\LINK] requieren [LINK=TECH_PLASTICS]Plástico[\LINK].[NEWLINE][NEWLINE][BOLD]Cambios en los edificios[\BOLD][NEWLINE]Los [LINK=BUILDING_AIRPORT]Aeropuertos[\LINK] dan +3 PX a todas las unidades aéreas y permiten a cada ciudad albergar cuatro unidades aéreas adicionales (hasta un total de ocho).[NEWLINE]El [LINK=BUILDING_PALACE]Palacio[\LINK] da +4 puntos de espionaje por turno.[NEWLINE]La [LINK=BUILDING_COURTHOUSE]Delegación[\LINK] da +2 puntos de espionaje y 1 espía especialista.[NEWLINE]El [LINK=BUILDING_CASTLE]Castillo[\LINK] da +25%% a los puntos de espionaje.[NEWLINE]La [LINK=BUILDING_JAIL]Cárcel[\LINK] da +4 puntos de espionaje, +50%% a los puntos de espionaje y dos espías especialistas.[NEWLINE]El [LINK=BUILDING_LABORATORY]Laboratorio[\LINK] requiere [LINK=TECH_SUPERCONDUCTORS]Superconductor[\LINK].[NEWLINE]La [LINK=BUILDING_FACTORY]Fábrica[\LINK] provoca ahora insalubridad si se tiene acceso al carbón o al petróleo.[NEWLINE]El [LINK=BUILDING_STABLE]Establo[\LINK] quedará obsoleto con el [LINK=TECH_ADVANCED_FLIGHT]Vuelo avanzado[\LINK].[NEWLINE]Los [LINK=BUILDING_OBELISK]Monumentos[\LINK] quedarán obsoletos con la [LINK=TECH_ASTRONOMY]Astronomía[\LINK].[NEWLINE]La [LINK=BUILDING_MILITARY_ACADEMY]Academia militar[\LINK] solo podrá construirse tras haber investigado la [LINK=TECH_MILITARY_SCIENCE]Belicología[\LINK].[NEWLINE][NEWLINE][BOLD]Cambios en las unidades[\BOLD][NEWLINE]Los espías han cambiado mucho. Visita [LINK=CONCEPT_ESPIONAGE]Espionaje[\LINK] para obtener más información.[NEWLINE]Las unidades montadas y de helicópteros ahora realizan [LINK=CONCEPT_FLANK_ATTACK]Flanqueos[\LINK] contra las armas de asedio. Ver los artículos al respecto para obtener más detalles.[NEWLINE]El [LINK=UNIT_JAPAN_SAMURAI]Samurái[\LINK] japonés empieza ahora con el ascenso "Instrucción I".[NEWLINE]La [LINK=UNIT_GREEK_PHALANX]Falange[\LINK] griega sustituye al [LINK=UNIT_AXEMAN]Soldado con hacha[\LINK].[NEWLINE]El [LINK=UNIT_GRENADIER]Granadero[\LINK] requiere [LINK=TECH_MILITARY_SCIENCE]Belicología[\LINK], no [LINK=TECH_CHEMISTRY]Química[\LINK].[NEWLINE]La [LINK=UNIT_CAVALRY]Caballería[\LINK] requiere [LINK=TECH_RIFLING]Fusil[\LINK] además de [LINK=TECH_MILITARY_TRADITION]Tradición militar[\LINK].[NEWLINE]La [LINK=UNIT_SAM_INFANTRY]Infantería con misiles tierra-aire[\LINK] recibe una bonificación del 75%% contra las unidades de helicópteros.[NEWLINE]Las unidades de misiles tierra-aire reciben el ascenso [LINK=CONCEPT_AIR_PROMOTIONS]Intercepción[\LINK].[NEWLINE]El [LINK=UNIT_TRIREME]Trirreme[\LINK] requiere [LINK=TECH_METAL_CASTING]Vaciado del metal[\LINK].[NEWLINE]Los [LINK=UNIT_GUNSHIP]Helicópteros de combate[\LINK] y los [LINK=UNIT_JET_FIGHTER]Cazas a reacción[\LINK] solo requieren [LINK=TECH_ADVANCED_FLIGHT]Vuelo avanzado[\LINK].[NEWLINE][LINK=CIVILIZATION_SPAIN]España[\LINK] puede construir [LINK=UNIT_KNIGHT]Caballeros[\LINK], ya que el [LINK=UNIT_SPANISH_CONQUISTADOR]Conquistador[\LINK] sustituye al [LINK=UNIT_CUIRASSIER]Coracero[\LINK].[NEWLINE]Solo puedes tener 4 unidades aéreas a la vez en una ciudad. Con un [LINK=BUILDING_AIRPORT]Aeropuerto[\LINK] construido, puedes albergar 8.[NEWLINE]La cantidad de experiencia necesaria para producir [LINK=UNIT_GREAT_GENERAL]grandes generales[\LINK] sucesivos ha aumentado.[NEWLINE]El cañoneo reduce las defensas de una ciudad en una cantidad fija, en lugar de en un porcentaje.[NEWLINE][NEWLINE][BOLD]Cambios en las maravillas[\BOLD][NEWLINE][LINK=BUILDING_SCOTLAND_YARD]Scotland Yard[\LINK] solo puede ser construido por un [LINK=UNIT_GREAT_SPY]Gran espía[\LINK] y da un +100%% a espionaje y +2 puntos de gran espía.[NEWLINE]El [LINK=BUILDING_PENTAGON]Pentágono[\LINK] da +2 puntos de gran espía.[NEWLINE]La [LINK=BUILDING_GREAT_PALACE]Ciudad Prohibida[\LINK] da +1 punto de gran espía.[NEWLINE]El [LINK=BUILDING_KREMLIN]Kremlin[\LINK] permite la creación de dos espías especialistas y da +2 puntos de gran espía.[NEWLINE][LINK=BUILDING_WEST_POINT]West Point[\LINK] da +2 puntos de gran espía.[NEWLINE][LINK=BUILDING_GREAT_WALL]La Gran Muralla[\LINK] da dos puntos de grandes personajes (gran espía).[NEWLINE]La [LINK=BUILDING_SISTINE_CHAPEL]Capilla Sixtina[\LINK] da +5 a cultura por cada templo de religión oficial que haya en una ciudad y puede construirse tras investigar la [LINK=TECH_MUSIC]Música[\LINK].[NEWLINE][LINK=BUILDING_NOTRE_DAME]Notre Dame[\LINK] da + 2 a Felicidad en todas las ciudades del continente y puede construirse tras investigar la [LINK=TECH_ENGINEERING]Ingeniería[\LINK].[NEWLINE]El [LINK=BUILDING_PARTHENON]Partenón[\LINK] requiere [LINK=TECH_AESTHETICS]Estética[\LINK].[NEWLINE][LINK=BUILDING_HAGIA_SOPHIA]Santa Sofía[\LINK] requiere [LINK=TECH_THEOLOGY]Teología[\LINK].[NEWLINE][LINK=BUILDING_STONEHENGE]Stonehenge[\LINK] quedará obsoleto con la [LINK=TECH_ASTRONOMY]Astronomía[\LINK].[NEWLINE]Todas las maravillas nacionales proporcionan ahora +1 punto de gran personaje en vez de +2.[NEWLINE][NEWLINE][BOLD]Cambios en los principios[\BOLD][NEWLINE]El coste de mantenimiento de la [LINK=CIVIC_SLAVERY]Esclavitud[\LINK] ha cambiado a medio.[NEWLINE]El [LINK=CIVIC_MERCANTILISM]mercantilismo[\LINK] hace que las corporaciones extranjeras no tengan efecto en tus ciudades.[NEWLINE]El [LINK=CIVIC_FREE_MARKET]Mercado libre[\LINK] reduce el mantenimiento de la corporación en un 25%%.[NEWLINE]La [LINK=CIVIC_STATE_PROPERTY]Propiedad estatal[\LINK] deja sin efecto a todas las corporaciones que haya en tus ciudades y da un +10%% de bonificación a la producción en todas las ciudades.[NEWLINE]La [LINK=CIVIC_NATIONHOOD]Patria[\LINK] da un +25%% de bonificación a los puntos de espionaje.[NEWLINE]El [LINK=CIVIC_CASTE_SYSTEM]Sistema de castas[\LINK] da una bonificación a la producción de los talleres.[NEWLINE]El [LINK=CIVIC_ENVIRONMENTALISM]Ecologismo[\LINK] da una bonificación al comercio por las [LINK=CONCEPT_BTS_FOREST_PRESERVE]Reservas forestales[\LINK] y los molinos de viento, pero a costa de aumentar el mantenimiento de la corporación en un 25%%.[NEWLINE][NEWLINE][BOLD]Cambios en los proyectos[\BOLD][NEWLINE]En la pantalla de victoria verás tu nave espacial y todas las piezas que hayas completado.[NEWLINE]Ahora una nave espacial puede despegar sin todo el revestimiento completo, pero cada pieza que le falte incrementará mucho el riesgo de fallo.[NEWLINE]El [LINK=PROJECT_SS_CASING]Revestimiento para naves espaciales[\LINK] requiere [LINK=TECH_COMPOSITES]Compuestos[\LINK], en lugar de [LINK=TECH_ROCKETRY]Cohetería[\LINK].[NEWLINE]El [LINK=PROJECT_SS_DOCKING_BAY]Muelle de acoplamiento para naves espaciales[\LINK] requiere [LINK=TECH_SATELLITES]Satélites[\LINK] en lugar de [LINK=TECH_ROBOTICS]Robótica[\LINK].[NEWLINE]La [LINK=PROJECT_SDI]SDI[\LINK] requiere [LINK=TECH_LASER]Láser[\LINK].[NEWLINE][LINK=PROJECT_THE_INTERNET]Internet[\LINK] requiere [LINK=TECH_COMPUTERS]Ordenadores[\LINK].[NEWLINE]Los [LINK=PROJECT_SS_THRUSTERS]Propulsores para naves espaciales[\LINK] requieren [LINK=TECH_SUPERCONDUCTORS]Superconductores[\LINK].[NEWLINE]Ya puede retrasarse la llegada de las naves espaciales, y también es posible lanzarlas con sistemas repetidos para aumentar las posibilidades de éxito o acelerar la hora de llegada. También pueden lanzarse sin ciertos sistemas, pero esto incrementará el riesgo de fallo.[NEWLINE][NEWLINE][BOLD]Cambios en las mejoras[\BOLD][NEWLINE]Los fuertes han cambiado considerablemente. Visita la sección [LINK=CONCEPT_FORT]Fuertes[\LINK] para una explicación a fondo.[NEWLINE]Los ferrocarriles pueden construirse con petróleo o carbón.[NEWLINE][NEWLINE][BOLD]Cambios en la interfaz[\BOLD][NEWLINE]Puedes ver tus misiones en activo en la pantalla del historial [CTRL + TAB].[NEWLINE]El Consejero de Asuntos Exteriores se ha mejorado.[NEWLINE]La pantalla "Los Albores del Hombre" se ha ampliado.[NEWLINE]Los turnos transcurridos, la investigación y los puntos de espionaje por turno se muestran en la pantalla principal.[NEWLINE]Las unidades de la Civilopedia muestran todas las unidades exclusivas que las sustituyen.[NEWLINE]La pantalla de estadísticas muestra ahora la clasificación económica exacta.[NEWLINE]Los enemigos que entren en tu territorio aparecerán marcados con un indicador rojo.[NEWLINE]Hacer clic en tu propia puntuación minimizará la lista de líderes.[NEWLINE]Pulsa [CTRL + H] para seleccionar todas las unidades heridas en una casilla específica.[NEWLINE][NEWLINE][BOLD]Cambios en el juego[\BOLD][NEWLINE]Las partidas a velocidad normal ahora tienen 500 turnos, pero el transcurso del tiempo se ha ajustado, por lo que el juego todavía acaba en 2050 d. C.[NEWLINE]Las [LINK=BUILDING_UNITED_NATIONS]Naciones Unidas[\LINK] han crecido enormemente. Visita la sección [LINK=CONCEPT_APOSTOLIC_PALACE]Palacio Apostólico[\LINK] para obtener más detalles.[NEWLINE]Las edades de oro incrementan en un +100%% la tasa de grandes personajes en tus ciudades.[NEWLINE]Solo necesitas un gran personaje en tu primera edad de oro, en lugar de dos.[NEWLINE]No se produce la anarquía al cambiar de principios y de religión durante una edad de oro.[NEWLINE]Para empezar una partida personalizada para un solo jugador o multijugador, puedes seleccionar la opción "Líderes sin restricciones" para jugar con cualquier líder o civilización.[NEWLINE]Seleccionar la opción "Elegir religión" te permite seleccionar qué religión te tocará cuando descubras una tecnología que funde religiones.[NEWLINE]Las rutas comerciales intercontinentales, tanto nacionales como extranjeras, rinden un cien por cien más.[NEWLINE]Debes investigar la Navegación a vela para poder intercambiar en la costa o los ríos fuera de tus fronteras.[NEWLINE]Las religiones ya no confieren visibilidad dentro de una ciudad.[NEWLINE]Los superespecialistas (grandes personajes que se añaden a las ciudades como especialistas) ahora permanecen en la ciudad incluso si ésta es tomada.[NEWLINE]Solo puedes construir cinco maravillas nacionales en un reto de una sola ciudad.[NEWLINE]Puedes intercambiar recursos que ya poseas.[NEWLINE][NEWLINE][BOLD]Cambios en los rasgos[\BOLD][NEWLINE]El rasgo Comunicativo solo aumenta el ritmo de producción de los trabajadores en un 25%% (antes era un 50%%).[NEWLINE][LINK=LEADER_AUGUSTUS]César Augusto[\LINK] es un líder Imperialista/Diligente en lugar de Organizado/Creativo.[NEWLINE][NEWLINE][BOLD]Cambios en los ascensos[NEWLINE][\BOLD]Las unidades aéreas cuentan ahora con sus propios [LINK=CONCEPT_AIR_PROMOTIONS]ascensos[\LINK].[NEWLINE]Nuevo ascenso, Montaraz III: Cura a las unidades de la misma casilla un 15%% por turno, +50%% al ataque en la selva y en el bosque.[NEWLINE][LINK=PROMOTION_GUERILLA3]Guerrilla III[\LINK] ahora tiene un +50%% de probabilidad de retirarse.[NEWLINE]La [LINK=TECH_MILITARY_SCIENCE]Belicología[\LINK] da acceso a los ascensos "Bombardeo aéreo" y "Comando".[NEWLINE]Las unidades con armas de pólvora pueden acceder al ascenso "Instrucción".[NEWLINE][NEWLINE][BOLD]Cambios en el modo multijugador[NEWLINE][\BOLD]Turnos simultáneos de los equipos: En las partidas multijugador, los jugadores de un mismo equipo pueden llevar a cabo sus turnos simultáneamente.[NEWLINE][NEWLINE][BOLD]Cambios en el "modding"[NEWLINE][\BOLD]En la pantalla del creador de mundos puedes colocar fronteras culturales sin la presencia de una ciudad.[NEWLINE]Los mods pueden tener ahora sus propios temas de GFC.[NEWLINE]Se ha añadido un sistema modular XML.[NEWLINE][NEWLINE][BOLD]Cambios en los gráficos[\BOLD][NEWLINE]Cada uno de los estilos artísticos (de Oriente Medio, grecorromano, etc.) cuenta con sus unidades de estilo propio. Esto quiere decir que las naves de exploración creadas por Carlomagno y las creadas por Suryavarman II tendrán un aspecto diferente aunque funcionen de igual manera.[NEWLINE]Se han implementado nuevos estilos de carreteras: romanas y modernas. + + + TXT_KEY_UNIT_GREEK_PHALANX_STRATEGY + This powerful melee combat unit (the Greek replacement for the [COLOR_UNIT_TEXT]Axeman[COLOR_REVERT]) is not as vulnerable to Chariots as Axemen are. + Cette puissante unité de combat rapproché (l'unité grecque qui remplace les [COLOR_UNIT_TEXT]soldats avec hache[COLOR_REVERT]) est moins vulnérable aux chars que les soldats avec hache. + Diese effektive Nahkampfeinheit (die griechische Variante des [COLOR_UNIT_TEXT]Axtkämpfers[COLOR_REVERT]) ist im Kampf gegen Streitwagen nicht so unterlegen wie der Axtkämpfer. + Questa potente unità da mischia (l'equivalente greco del [COLOR_UNIT_TEXT]Guerriero con ascia[COLOR_REVERT]) non è così vulnerabile ai carri da guerra. + Esta poderosa unidad de cuerpo a cuerpo (el equivalente griego al [COLOR_UNIT_TEXT]Soldado con hacha[COLOR_REVERT]) no es tan vulnerable a los Carros como lo son los Soldados con hacha. + + + TXT_KEY_BUILDING_PUBLIC_TRANSPORTATION_STRATEGY + [COLOR_BUILDING_TEXT]Public Transportation[COLOR_REVERT] provides a bonus to health in your city and an added bonus for access to [COLOR_HIGHLIGHT_TEXT]Oil[COLOR_REVERT] or when under [COLOR_HIGHLIGHT_TEXT]Environmentalism[COLOR_REVERT]. + Les [COLOR_BUILDING_TEXT]Transports publics[COLOR_REVERT] confèrent un bonus de santé à votre ville et un bonus supplémentaire dû à l'accès au [COLOR_HIGHLIGHT_TEXT]pétrole[COLOR_REVERT] ou sous la doctrine [COLOR_HIGHLIGHT_TEXT]Ecologie[COLOR_REVERT]. + [COLOR_BUILDING_TEXT]Öffentliche Verkehrsmittel[COLOR_REVERT] erhöhen die Gesundheit in einer Stadt und gewähren einen zusätzlichen Bonus für den Zugang zu [COLOR_HIGHLIGHT_TEXT]Öl[COLOR_REVERT] oder für die Staatsform [COLOR_HIGHLIGHT_TEXT]Umweltschutz[COLOR_REVERT]. + I [COLOR_BUILDING_TEXT]Trasporti pubblici[COLOR_REVERT] danno un bonus alla salute della tua città e un bonus aggiuntivo sei hai accesso al [COLOR_HIGHLIGHT_TEXT]Petrolio[COLOR_REVERT] oppure se hai adottato la forma di governo [COLOR_HIGHLIGHT_TEXT]Ambientalismo[COLOR_REVERT]. + El [COLOR_BUILDING_TEXT]Transporte público[COLOR_REVERT] da una bonificación a la salud de la ciudad y una bonificación añadida por acceder al [COLOR_HIGHLIGHT_TEXT]Petróleo[COLOR_REVERT] o cuando se funciona bajo el [COLOR_HIGHLIGHT_TEXT]Ecologismo[COLOR_REVERT]. + + + TXT_KEY_MAIN_MENU_ABOUT_CIV4 + About Beyond the Sword + A propos de Beyond the Sword + Über Beyond the Sword + A proposito di Beyond the Sword + Acerca de Beyond the Sword + + + TXT_KEY_TECH_ALPHABET_STRATEGY + [COLOR_TECH_TEXT]Alphabet[COLOR_REVERT] allows you to trade technologies with other civilizations and lets you build [COLOR_UNIT_TEXT]Spies[COLOR_REVERT] in cities. + L'[COLOR_TECH_TEXT]Alphabet[COLOR_REVERT] permet d'échanger des technologies avec d'autres civilisations et de construire des [COLOR_HIGHLIGHT_TEXT]Espions[COLOR_REVERT] dans les villes. + Das [COLOR_TECH_TEXT]Alphabet[COLOR_REVERT] ermöglicht Ihnen den Austausch von Technologien mit anderen Zivilisationen und die Ausbildung von [COLOR_HIGHLIGHT_TEXT]Spionen[COLOR_REVERT] in Städten. + L'[COLOR_TECH_TEXT]Alfabeto[COLOR_REVERT] permette gli scambi tecnologici con le altre civiltà e lo sviluppo delle [COLOR_UNIT_TEXT]Spie[COLOR_REVERT] nelle città. + El [COLOR_TECH_TEXT]Alfabeto[COLOR_REVERT] permite intercambiar tecnologías con otras civilizaciones y generar [COLOR_UNIT_TEXT]Espías[COLOR_REVERT] en las ciudades. + + + TXT_KEY_TECH_MILITARY_SCIENCE_STRATEGY + [COLOR_TECH_TEXT]Military Science[COLOR_REVERT] allows the construction of the [COLOR_UNIT_TEXT]Grenadier[COLOR_REVERT] and the [COLOR_UNIT_TEXT]Ship of the Line[COLOR_REVERT] units and the [COLOR_BUILDING_TEXT]Military Academy[COLOR_REVERT] building. It also allows access to the [COLOR_HIGHLIGHT_TEXT]Blitz[COLOR_REVERT] and [COLOR_HIGHLIGHT_TEXT]Commando[COLOR_REVERT] promotions. + La[COLOR_TECH_TEXT]Science militaire[COLOR_REVERT] permet la construction des [COLOR_UNIT_TEXT]Grenadiers[COLOR_REVERT] et du [COLOR_UNIT_TEXT]Galion de guerre[COLOR_REVERT] ainsi que du bâtiment [COLOR_BUILDING_TEXT]Académie militaire[COLOR_REVERT]. Elle permet également d'accéder aux promotions [COLOR_HIGHLIGHT_TEXT]Blitz[COLOR_REVERT] et [COLOR_HIGHLIGHT_TEXT]Commando[COLOR_REVERT]. + Die [COLOR_TECH_TEXT]Militärwissenschaft[COLOR_REVERT] erlaubt die Ausbildung des [COLOR_UNIT_TEXT]Grenadiers[COLOR_REVERT] sowie den Bau des [COLOR_UNIT_TEXT]Linienschiffs[COLOR_REVERT] und der [COLOR_BUILDING_TEXT]Militärakademie[COLOR_REVERT]. Außerdem ermöglicht sie den Zugang zu den Beförderungen [COLOR_HIGHLIGHT_TEXT]Blitzkrieg[COLOR_REVERT] und [COLOR_HIGHLIGHT_TEXT]Kommando[COLOR_REVERT]. + La [COLOR_TECH_TEXT]Scienza militare[COLOR_REVERT] permette di costruire le unità [COLOR_UNIT_TEXT]Granatiere[COLOR_REVERT] e [COLOR_UNIT_TEXT]Nave da prima linea[COLOR_REVERT] e l'edificio [COLOR_BUILDING_TEXT]Accademia militare[COLOR_REVERT]. Permette anche di accedere alle promozioni [COLOR_HIGHLIGHT_TEXT]Incursione[COLOR_REVERT] e [COLOR_HIGHLIGHT_TEXT]Commando[COLOR_REVERT]. + La [COLOR_TECH_TEXT]Belicología[COLOR_REVERT] permite la construcción de las unidades del [COLOR_UNIT_TEXT]Granadero[COLOR_REVERT] y del [COLOR_UNIT_TEXT]Buque de guerra[COLOR_REVERT], así como del edificio de la [COLOR_BUILDING_TEXT]Academia militar[COLOR_REVERT]. También permite acceder a los ascensos de [COLOR_HIGHLIGHT_TEXT]Bombardeo aéreo[COLOR_REVERT] y de [COLOR_HIGHLIGHT_TEXT]Comando[COLOR_REVERT]. + + + TXT_KEY_TECH_PHYSICS_STRATEGY + The first civilization to discover [COLOR_TECH_TEXT]Physics[COLOR_REVERT] receives a [COLOR_UNIT_TEXT]Great Scientist[COLOR_REVERT]. It also enables the [COLOR_UNIT_TEXT]Airship[COLOR_REVERT] unit and reveals the [COLOR_HIGHLIGHT_TEXT]Uranium[COLOR_REVERT] resource. + La première civilisation qui découvre la [COLOR_TECH_TEXT]Physique[COLOR_REVERT] obtient un [COLOR_UNIT_TEXT]Savant illustre[COLOR_REVERT]. Elle permet la construction d'[COLOR_UNIT_TEXT]Avions[COLOR_REVERT]. Elle fait également apparaître l'[COLOR_HIGHLIGHT_TEXT]uranium[COLOR_REVERT] sur la carte. + Die erste Zivilisation, die die [COLOR_TECH_TEXT]Physik[COLOR_REVERT] entdeckt, erhält einen [COLOR_UNIT_TEXT]Großen Wissenschaftler[COLOR_REVERT] und kann das [COLOR_UNIT_TEXT]Luftschiff[COLOR_REVERT] bauen. Diese Technologie deckt auch die Ressource [COLOR_HIGHLIGHT_TEXT]Uran[COLOR_REVERT] auf. + Chi ricerca per primo la [COLOR_TECH_TEXT]Fisica[COLOR_REVERT] riceve un [COLOR_UNIT_TEXT]Grande Scienziato[COLOR_REVERT], sblocca il [COLOR_UNIT_TEXT]Dirigibile[COLOR_REVERT] e rivela la risorsa [COLOR_HIGHLIGHT_TEXT]Uranio[COLOR_REVERT]. + La primera civilización en descubrir la [COLOR_TECH_TEXT]Física[COLOR_REVERT] recibe un [COLOR_UNIT_TEXT]Gran científico[COLOR_REVERT]. También activa la unidad del [COLOR_UNIT_TEXT]Dirigible[COLOR_REVERT] y revela el recurso del [COLOR_HIGHLIGHT_TEXT]Uranio[COLOR_REVERT]. + + + TXT_KEY_TECH_MEDICINE_STRATEGY + [COLOR_TECH_TEXT]Medicine[COLOR_REVERT] allows you to construct the [COLOR_BUILDING_TEXT]Hospital[COLOR_REVERT] city improvement, the [COLOR_BUILDING_TEXT]Sid's Sushi Co.[COLOR_REVERT] wonder and the [COLOR_BUILDING_TEXT]Red Cross[COLOR_REVERT] national wonder. It enables the [COLOR_HIGHLIGHT_TEXT]Environmentalism[COLOR_REVERT] civic. + La [COLOR_TECH_TEXT]Médecine[COLOR_REVERT] permet de construire des [COLOR_BUILDING_TEXT]Hôpitaux[COLOR_REVERT], la société commerciale [COLOR_BUILDING_TEXT]Sid's sushis Co.[COLOR_REVERT] et la [COLOR_BUILDING_TEXT]Croix-Rouge[COLOR_REVERT]. Elle permet d'accéder à la doctrine [COLOR_HIGHLIGHT_TEXT]Ecologie[COLOR_REVERT]. + Die [COLOR_TECH_TEXT]Medizin[COLOR_REVERT] ermöglicht den Bau des [COLOR_BUILDING_TEXT]Krankenhauses[COLOR_REVERT] als Stadt-Modernisierung, des Wunders [COLOR_BUILDING_TEXT]Sid's Sushi Company[COLOR_REVERT] und des Nationalen Wunders [COLOR_BUILDING_TEXT]Rotes Kreuz[COLOR_REVERT]. Außerdem wird die Staatsform [COLOR_HIGHLIGHT_TEXT]Umweltschutz[COLOR_REVERT] verfügbar. + La [COLOR_TECH_TEXT]Medicina[COLOR_REVERT] permette la realizzazione del miglioramento cittadino [COLOR_BUILDING_TEXT]Ospedale[COLOR_REVERT], della meraviglia [COLOR_BUILDING_TEXT]Sid Sushi[COLOR_REVERT] e della Meraviglia Nazionale [COLOR_BUILDING_TEXT]Croce Rossa[COLOR_REVERT]. Inoltre, permette la realizzazione della forma di governo [COLOR_HIGHLIGHT_TEXT]Ambientalismo[COLOR_REVERT]. + La [COLOR_TECH_TEXT]Medicina[COLOR_REVERT] permite construir la mejora urbana del [COLOR_BUILDING_TEXT]Hospital[COLOR_REVERT], la maravilla de [COLOR_BUILDING_TEXT]Sid's Sushi[COLOR_REVERT] y la maravilla nacional de la [COLOR_BUILDING_TEXT]Cruz Roja[COLOR_REVERT]. Activa el principio del [COLOR_HIGHLIGHT_TEXT]Ecologismo[COLOR_REVERT]. + + + TXT_KEY_TECH_RAILROAD_STRATEGY + [COLOR_TECH_TEXT]Railroad[COLOR_REVERT] allows construction of [COLOR_UNIT_TEXT]Machine Gun[COLOR_REVERT] units and the [COLOR_BUILDING_TEXT]Mining Inc[COLOR_REVERT] wonder. Most importantly, with [COLOR_HIGHLIGHT_TEXT]Coal[COLOR_REVERT] or [COLOR_HIGHLIGHT_TEXT]Oil[COLOR_REVERT] it allows your workers to upgrade your [COLOR_HIGHLIGHT_TEXT]Roads[COLOR_REVERT] to [COLOR_HIGHLIGHT_TEXT]Railroads[COLOR_REVERT], vastly increasing your units' movement. + La [COLOR_TECH_TEXT]Voie ferrée[COLOR_REVERT] permet la construction de [COLOR_UNIT_TEXT]Mitrailleuses[COLOR_REVERT] et de la société commerciale [COLOR_BUILDING_TEXT]Compagnie d'exploitation minière[COLOR_REVERT]. Mais surtout, avec du [COLOR_HIGHLIGHT_TEXT]charbon[COLOR_REVERT] ou du [COLOR_HIGHLIGHT_TEXT]pétrole[COLOR_REVERT], elle permet à vos ouvriers d'améliorer vos [COLOR_HIGHLIGHT_TEXT]routes[COLOR_REVERT] en [COLOR_HIGHLIGHT_TEXT]voies ferrées[COLOR_REVERT], accélérant très nettement le déplacement de vos unités. + Die [COLOR_TECH_TEXT]Eisenbahn[COLOR_REVERT] ermöglicht den Bau von [COLOR_UNIT_TEXT]Maschinengewehren[COLOR_REVERT] und das Wunder [COLOR_BUILDING_TEXT]Mining Inc.[COLOR_REVERT]. Besonders wichtig: Mit [COLOR_HIGHLIGHT_TEXT]Kohle[COLOR_REVERT] oder [COLOR_HIGHLIGHT_TEXT]Öl[COLOR_REVERT] erlaubt sie Ihnen, Ihre [COLOR_HIGHLIGHT_TEXT]Straßen[COLOR_REVERT] zu [COLOR_HIGHLIGHT_TEXT]Eisenbahn[COLOR_REVERT] zu verbessern, so dass sich Ihre Einheiten bedeutend schneller fortbewegen. + La [COLOR_TECH_TEXT]Ferrovia[COLOR_REVERT] permette la realizzazione dei [COLOR_UNIT_TEXT]Mitragliatori[COLOR_REVERT] e della meraviglia [COLOR_BUILDING_TEXT]Estrazioni Minerarie Inc.[COLOR_REVERT]. Inoltre, insieme al [COLOR_HIGHLIGHT_TEXT]Carbone[COLOR_REVERT] o al [COLOR_HIGHLIGHT_TEXT]Petrolio[COLOR_REVERT], permette ai lavoratori di aggiornare le [COLOR_HIGHLIGHT_TEXT]strade[COLOR_REVERT] in [COLOR_HIGHLIGHT_TEXT]ferrovie[COLOR_REVERT], migliorando notevolmente il movimento delle unità. + El [COLOR_TECH_TEXT]Ferrocarril[COLOR_REVERT] permite la construcción de las unidades de [COLOR_UNIT_TEXT]Ametralladoras[COLOR_REVERT] y la maravilla de [COLOR_BUILDING_TEXT]Mining Inc.[COLOR_REVERT]. Y, lo que es más importante, junto con el [COLOR_HIGHLIGHT_TEXT]Carbón[COLOR_REVERT] o el [COLOR_HIGHLIGHT_TEXT]Petróleo[COLOR_REVERT] permite a los trabajadores modernizar las [COLOR_HIGHLIGHT_TEXT]Carreteras[COLOR_REVERT] y convertirlas en [COLOR_HIGHLIGHT_TEXT]Ferrocarriles[COLOR_REVERT], lo que aumenta enormemente el movimiento de las unidades. + + + TXT_KEY_TECH_SAILING_STRATEGY + [COLOR_TECH_TEXT]Sailing[COLOR_REVERT] allows you to build the [COLOR_UNIT_TEXT]Galley[COLOR_REVERT] unit. It also enables trading along coasts and rivers, as well as the construction of the [COLOR_BUILDING_TEXT]Lighthouse[COLOR_REVERT] city improvement and the [COLOR_BUILDING_TEXT]Moai Statues[COLOR_REVERT]. + La [COLOR_TECH_TEXT]Navigation à voile[COLOR_REVERT] vous permet de construire l'unité [COLOR_UNIT_TEXT]Galère[COLOR_REVERT] et de faire du commerce le long des côtes et des cours d'eau. Elle permet aussi la construction du [COLOR_BUILDING_TEXT]Phare[COLOR_REVERT] et des [COLOR_BUILDING_TEXT]Statues Moaï[COLOR_REVERT]. + Das [COLOR_TECH_TEXT]Segeln[COLOR_REVERT] ermöglicht Ihnen den Bau einer [COLOR_UNIT_TEXT]Galeere[COLOR_REVERT], den Handel an Küsten und Flüssen, sowie die Errichtung eines [COLOR_BUILDING_TEXT]Leuchtturms[COLOR_REVERT]. + La [COLOR_TECH_TEXT]Navigazione[COLOR_REVERT] permette la realizzazione di [COLOR_UNIT_TEXT]galee[COLOR_REVERT]. Inoltre, premette gli scambi marittimi e fluviali e la costruzione del miglioramento cittadino [COLOR_BUILDING_TEXT]Faro[COLOR_REVERT] e delle [COLOR_BUILDING_TEXT]Statue Moai[COLOR_REVERT]. + La [COLOR_TECH_TEXT]Navegación a vela[COLOR_REVERT] permite construir la unidad de la [COLOR_UNIT_TEXT]Galera[COLOR_REVERT]. También activa el comercio a lo largo de costas y ríos, así como la construcción de la mejora urbana del [COLOR_BUILDING_TEXT]Faro[COLOR_REVERT] y la maravilla de [COLOR_BUILDING_TEXT]Los Moai[COLOR_REVERT]. + + + TXT_KEY_BUILDING_CORPORATION_1_STRATEGY + Build the [COLOR_BUILDING_TEXT]Cereal Mills[COLOR_REVERT] Headquarters to create the [COLOR_HIGHLIGHT_TEXT]Cereal Mills Corporation[COLOR_REVERT], which consumes [COLOR_HIGHLIGHT_TEXT]Wheat[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Corn[COLOR_REVERT] or [COLOR_HIGHLIGHT_TEXT]Rice[COLOR_REVERT] and adds a food bonus to cities where the [COLOR_HIGHLIGHT_TEXT]Cereal Mills Corporation[COLOR_REVERT] is present. The Headquarters provide gold for each city in the world with a Cereal Mills franchise. + Construisez le siège des [COLOR_BUILDING_TEXT]Grands Moulins céréaliers[COLOR_REVERT] pour créer la société commerciale [COLOR_HIGHLIGHT_TEXT]Grands Moulins céréaliers[COLOR_REVERT], qui consomme du [COLOR_HIGHLIGHT_TEXT]blé[COLOR_REVERT], du [COLOR_HIGHLIGHT_TEXT]maïs[COLOR_REVERT] ou du [COLOR_HIGHLIGHT_TEXT]riz[COLOR_REVERT] et confère un bonus de nourriture aux villes où les [COLOR_HIGHLIGHT_TEXT]Grands Moulins céréaliers[COLOR_REVERT] sont présents. Il confère également un bonus culturel et un bonus d'or. + Der Bau des Unternehmenssitzes der [COLOR_BUILDING_TEXT]Cereal Mills[COLOR_REVERT] bildet die Grundlage für die Errichtung der Kapitalgesellschaft [COLOR_HIGHLIGHT_TEXT]Cereal Mills Inc.[COLOR_REVERT], welche [COLOR_HIGHLIGHT_TEXT]Weizen[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Mais[COLOR_REVERT] oder [COLOR_HIGHLIGHT_TEXT]Reis[COLOR_REVERT] verarbeitet. Die [COLOR_HIGHLIGHT_TEXT]Cereal Mills Inc.[COLOR_REVERT] gewährt jeder Stadt, in der sie vertreten ist, einen Nahrungsmittelbonus. Der Unternehmenssitz bringt allen Städten der Welt mit einem Cereal Mills-Franchise Gold ein. + Costruisci il Quartier generale della [COLOR_BUILDING_TEXT]Mulini Cereali[COLOR_REVERT] per creare la [COLOR_HIGHLIGHT_TEXT]Corporazione Mulini Cereali[COLOR_REVERT], che consuma [COLOR_HIGHLIGHT_TEXT]Frumento[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Granoturco[COLOR_REVERT] o [COLOR_HIGHLIGHT_TEXT]Riso[COLOR_REVERT] e dà un bonus di cibo alle città in cui si trova. Il Quartier generale fornisce oro in ciascuna città dove è presente la Mulini Cereali. + Construye la sede de [COLOR_BUILDING_TEXT]Cereal Mills[COLOR_REVERT] para crear la [COLOR_HIGHLIGHT_TEXT]Corporación Cereal Mills[COLOR_REVERT], que consume [COLOR_HIGHLIGHT_TEXT]Trigo[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Maíz[COLOR_REVERT] o [COLOR_HIGHLIGHT_TEXT]Arroz[COLOR_REVERT] y suma una bonificación a los alimentos en las ciudades donde la corporación esté presente. La sede proporcionará oro para todas las ciudades del mundo en las que esté presente la franquicia Cereal Mills. + + + TXT_KEY_BUILDING_CORPORATION_2_STRATEGY + Build the [COLOR_BUILDING_TEXT]Sid's Sushi Company[COLOR_REVERT] Headquarters to create the [COLOR_HIGHLIGHT_TEXT]Sid's Sushi Corporation[COLOR_REVERT], which consumes [COLOR_HIGHLIGHT_TEXT]Clams[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Fish[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Crabs[COLOR_REVERT] and [COLOR_HIGHLIGHT_TEXT]Rice[COLOR_REVERT] and adds bonus food and culture to cities where the [COLOR_HIGHLIGHT_TEXT]Sid's Sushi Corporation[COLOR_REVERT] is present. The Headquarters provide gold for each city in the world with a Sid's Sushi franchise. + Construisez le siège de l'entreprise [COLOR_BUILDING_TEXT]Sid's Sushi[COLOR_REVERT] pour créer la [COLOR_HIGHLIGHT_TEXT]société commerciale Sid's Sushi[COLOR_REVERT], qui consomme des [COLOR_HIGHLIGHT_TEXT]coquillages[COLOR_REVERT], du [COLOR_HIGHLIGHT_TEXT]poisson[COLOR_REVERT], des [COLOR_HIGHLIGHT_TEXT]crabes[COLOR_REVERT] et du [COLOR_HIGHLIGHT_TEXT]riz[COLOR_REVERT], et procure un bonus de nourriture aux villes où la [COLOR_HIGHLIGHT_TEXT]société commerciale Sid's Sushi[COLOR_REVERT] est implantée. Il confère également un bonus culturel et un bonus d'or. + Der Bau des Unternehmenssitzes von [COLOR_BUILDING_TEXT]Sid's Sushi[COLOR_REVERT] bildet die Grundlage für die Errichtung der Kapitalgesellschaft [COLOR_HIGHLIGHT_TEXT]Sid's Sushi Company[COLOR_REVERT], welche [COLOR_HIGHLIGHT_TEXT]Muscheln[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Fisch[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Krabben[COLOR_REVERT] und [COLOR_HIGHLIGHT_TEXT]Reis[COLOR_REVERT] verarbeitet. Die [COLOR_HIGHLIGHT_TEXT]Sid's Sushi Company[COLOR_REVERT] gewährt jeder Stadt, in der sie vertreten ist, einen Nahrungs- und Kulturbonus. Der Unternehmenssitz bringt allen Städten der Welt mit einem Sid's Sushi-Franchise Gold ein. + Costruisci il Quartier generale della [COLOR_BUILDING_TEXT]Sid Sushi[COLOR_REVERT] per creare la [COLOR_HIGHLIGHT_TEXT]Corporazione Sid Sushi[COLOR_REVERT], che consuma [COLOR_HIGHLIGHT_TEXT]Molluschi[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Pesci[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Crostacei[COLOR_REVERT] e [COLOR_HIGHLIGHT_TEXT]Riso[COLOR_REVERT] e dà un bonus di cibo alle città in cui si trova. Il Quartier generale fornisce oro in ciascuna città dove è presente la Sid Sushi. + Construye la sede de la [COLOR_BUILDING_TEXT]Sid's Sushi Company[COLOR_REVERT] para crear la [COLOR_HIGHLIGHT_TEXT]Corporación Sid's Sushi[COLOR_REVERT], que consume [COLOR_HIGHLIGHT_TEXT]Almejas[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Pescado[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Cangrejos[COLOR_REVERT] y [COLOR_HIGHLIGHT_TEXT]Arroz[COLOR_REVERT], y suma una bonificación de alimentos y de cultura a las ciudades donde la corporación esté presente. La sede proporcionará oro para todas las ciudades del mundo en las que esté presente la franquicia Sid's Sushi. + + + TXT_KEY_BUILDING_CORPORATION_3_STRATEGY + Build the [COLOR_BUILDING_TEXT]Standard Ethanol[COLOR_REVERT] Headquarters to create the [COLOR_HIGHLIGHT_TEXT]Standard Ethanol Corporation[COLOR_REVERT], which consumes [COLOR_HIGHLIGHT_TEXT]Corn[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Sugar[COLOR_REVERT] and [COLOR_HIGHLIGHT_TEXT]Rice[COLOR_REVERT] and adds [COLOR_HIGHLIGHT_TEXT]Oil[COLOR_REVERT] and a research bonus to every city where the [COLOR_HIGHLIGHT_TEXT]Standard Ethanol Corporation[COLOR_REVERT] is present. The Headquarters provide gold for each city in the world with a Standard Ethanol franchise. + Construisez le siège d'[COLOR_BUILDING_TEXT]Ethanol Inc.[COLOR_REVERT] pour créer la [COLOR_HIGHLIGHT_TEXT]société commerciale Ethanol Inc.[COLOR_REVERT], qui consomme du [COLOR_HIGHLIGHT_TEXT]maïs[COLOR_REVERT], du [COLOR_HIGHLIGHT_TEXT]sucre[COLOR_REVERT] et du [COLOR_HIGHLIGHT_TEXT]riz[COLOR_REVERT], et génère du [COLOR_HIGHLIGHT_TEXT]pétrole[COLOR_REVERT] dans chaque ville où la [COLOR_HIGHLIGHT_TEXT]société commerciale Ethanol Inc.[COLOR_REVERT] est implantée. Il confère également un bonus culturel et un bonus d'or. + Der Bau des Unternehmenssitzes der [COLOR_BUILDING_TEXT]Standard Ethanol[COLOR_REVERT] bildet die Grundlage für die Errichtung der Kapitalgesellschaft [COLOR_HIGHLIGHT_TEXT]Standard Ethanol[COLOR_REVERT], welche [COLOR_HIGHLIGHT_TEXT]Mais[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Zucker[COLOR_REVERT] und [COLOR_HIGHLIGHT_TEXT]Reis[COLOR_REVERT] verarbeitet. Die [COLOR_HIGHLIGHT_TEXT]Standard Ethanol[COLOR_REVERT] versorgt eine Stadt mit [COLOR_HIGHLIGHT_TEXT]Öl[COLOR_REVERT] und gewährt jeder Stadt, in der sie vertreten ist, einen Forschungsbonus. Der Unternehmenssitz bringt allen Städten der Welt mit einem Standard Ethanol-Franchise Gold ein. + Costruisci il Quartier generale della [COLOR_BUILDING_TEXT]Etanolo Standard[COLOR_REVERT] per creare la [COLOR_HIGHLIGHT_TEXT]Corporazione Etanolo standard[COLOR_REVERT], che consuma [COLOR_HIGHLIGHT_TEXT]Granoturco[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Zucchero[COLOR_REVERT] e [COLOR_HIGHLIGHT_TEXT]Riso[COLOR_REVERT] e genera [COLOR_HIGHLIGHT_TEXT]Petrolio[COLOR_REVERT] in ogni città in cui si trova. Il Quartier generale fornisce oro in ciascuna città dove è presente la Etanolo Standard. + Construye la sede de la [COLOR_BUILDING_TEXT]Standard Ethanol[COLOR_REVERT] para crear la [COLOR_HIGHLIGHT_TEXT]Corporación Standard Ethanol[COLOR_REVERT], que consume [COLOR_HIGHLIGHT_TEXT]Maíz[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Azúcar[COLOR_REVERT] y [COLOR_HIGHLIGHT_TEXT]Arroz[COLOR_REVERT], y genera [COLOR_HIGHLIGHT_TEXT]Petróleo[COLOR_REVERT] y una bonificación de investigación en toda ciudad en la que la corporación esté presente. La sede proporcionará oro para todas las ciudades del mundo en las que esté presente la franquicia Standard Ethanol. + + + TXT_KEY_BUILDING_CORPORATION_4_STRATEGY + Build the [COLOR_BUILDING_TEXT]Creative Constructions[COLOR_REVERT] Headquarters to create the [COLOR_HIGHLIGHT_TEXT]Creative Constructions Corporation[COLOR_REVERT], which consumes [COLOR_HIGHLIGHT_TEXT]Iron[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Copper[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Stone[COLOR_REVERT] or [COLOR_HIGHLIGHT_TEXT]Marble[COLOR_REVERT] and adds a production and culture bonus to every city where the [COLOR_HIGHLIGHT_TEXT]Creative Constructions Corporation[COLOR_REVERT] is present. The Headquarters provide gold for each city in the world with a Creative Constructions franchise. + Construisez le siège des [COLOR_BUILDING_TEXT]Constructions Créatives[COLOR_REVERT] pour créer la société commerciale : [COLOR_HIGHLIGHT_TEXT]Constructions Créatives[COLOR_REVERT], qui consomme du [COLOR_HIGHLIGHT_TEXT]fer[COLOR_REVERT], du [COLOR_HIGHLIGHT_TEXT]cuivre[COLOR_REVERT], de la [COLOR_HIGHLIGHT_TEXT]pierre[COLOR_REVERT] ou du [COLOR_HIGHLIGHT_TEXT]marbre[COLOR_REVERT] et confère un bonus de production à chaque ville où les [COLOR_HIGHLIGHT_TEXT]Constructions Créatives[COLOR_REVERT] sont présentes. Il confère également un bonus culturel et un bonus d'or. + Der Bau des Unternehmenssitzes der [COLOR_BUILDING_TEXT]Creative Constructions[COLOR_REVERT] bildet die Grundlage für die Errichtung der Kapitalgesellschaft [COLOR_HIGHLIGHT_TEXT]Creative Constructions[COLOR_REVERT], welche [COLOR_HIGHLIGHT_TEXT]Eisen[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Kupfer[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Stein[COLOR_REVERT] oder [COLOR_HIGHLIGHT_TEXT]Marmor[COLOR_REVERT] verarbeitet. Die [COLOR_HIGHLIGHT_TEXT]Creative Constructions[COLOR_REVERT] gewährt jeder Stadt, in der sie vertreten ist, einen Produktions- und Kulturbonus. Der Unternehmenssitz bringt allen Städten der Welt mit einem Creative Constructions-Franchise Gold ein. + Costruisci il Quartier generale della [COLOR_BUILDING_TEXT]Creazioni Costruttive[COLOR_REVERT] per creare la [COLOR_HIGHLIGHT_TEXT]Corporazione Creazioni Costruttive[COLOR_REVERT], che consuma [COLOR_HIGHLIGHT_TEXT]Ferro[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Rame[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Pietra[COLOR_REVERT] o [COLOR_HIGHLIGHT_TEXT]Marmo[COLOR_REVERT] e dà un bonus di produzione e cultura in ogni città in cui si trova. Il Quartier generale fornisce oro in ciascuna città dove è presente la Creazioni Costruttive. + Construye la sede de la [COLOR_BUILDING_TEXT]Creative Constructions[COLOR_REVERT] para crear la [COLOR_HIGHLIGHT_TEXT]Corporación Creative Constructions[COLOR_REVERT], que consume [COLOR_HIGHLIGHT_TEXT]Hierro[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Cobre[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Piedra[COLOR_REVERT] o [COLOR_HIGHLIGHT_TEXT]Mármol[COLOR_REVERT] y suma una bonificación a la producción y a la cultura en toda ciudad en la que la corporación esté presente. La sede proporcionará oro para todas las ciudades del mundo en las que esté presente la franquicia Creative Constructions. + + + TXT_KEY_BUILDING_CORPORATION_5_STRATEGY + Build the [COLOR_BUILDING_TEXT]Mining Inc[COLOR_REVERT] Headquarters to create the [COLOR_HIGHLIGHT_TEXT]Mining Inc Corporation[COLOR_REVERT], which consumes [COLOR_HIGHLIGHT_TEXT]Aluminum[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Iron[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Copper[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Coal[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Silver[COLOR_REVERT] or [COLOR_HIGHLIGHT_TEXT]Gold[COLOR_REVERT] and adds a production bonus to any city where the [COLOR_HIGHLIGHT_TEXT]Mining Inc Corporation[COLOR_REVERT] is present. The Headquarters provide gold for each city in the world with a Mining Inc. franchise. + Construisez le siège de la [COLOR_BUILDING_TEXT]Compagnie d'exploitation minière[COLOR_REVERT] pour créer la société commerciale : [COLOR_HIGHLIGHT_TEXT]Compagnie d'exploitation minière[COLOR_REVERT], qui consomme du [COLOR_HIGHLIGHT_TEXT]Fer[COLOR_REVERT], du [COLOR_HIGHLIGHT_TEXT]Cuivre[COLOR_REVERT], du [COLOR_HIGHLIGHT_TEXT]charbon[COLOR_REVERT], de l'[COLOR_HIGHLIGHT_TEXT]argent[COLOR_REVERT] ou de l'[COLOR_HIGHLIGHT_TEXT]Or[COLOR_REVERT] et ajoute un bonus commercial à toute ville où la [COLOR_HIGHLIGHT_TEXT]Compagnie d'exploitation minière[COLOR_REVERT] est présente. Il confère également un bonus culturel et un bonus d'or. + Der Bau des Unternehmenssitzes der [COLOR_BUILDING_TEXT]Mining Inc.[COLOR_REVERT] bildet die Grundlage für die Errichtung der Kapitalgesellschaft [COLOR_HIGHLIGHT_TEXT]Mining Inc.[COLOR_REVERT], welche [COLOR_HIGHLIGHT_TEXT]Aluminium[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Eisen[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Kupfer[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Kohle[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Silber[COLOR_REVERT] oder [COLOR_HIGHLIGHT_TEXT]Gold[COLOR_REVERT] verarbeitet. Die [COLOR_HIGHLIGHT_TEXT]Mining Inc.[COLOR_REVERT] gewährt jeder Stadt, in der sie vertreten ist, einen Produktionsbonus. Der Unternehmenssitz bringt allen Städten der Welt mit einem Mining Inc.-Franchise Gold ein. + Costruisci il Quartier generale della [COLOR_BUILDING_TEXT]Estrazioni minerarie Inc[COLOR_REVERT] per creare la [COLOR_HIGHLIGHT_TEXT]Corporazione Estrazioni minerarie Inc[COLOR_REVERT], che consuma [COLOR_HIGHLIGHT_TEXT]Ferro[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Rame[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Carbone[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Oro[COLOR_REVERT] o [COLOR_HIGHLIGHT_TEXT]Argento[COLOR_REVERT] e dà un bonus di produzione a ogni città in cui si trova. Il Quartier generale fornisce oro in ciascuna città dove è presente la Estrazioni Minerarie Inc. + Construye la sede de la [COLOR_BUILDING_TEXT]Mining Inc.[COLOR_REVERT] para crear la corporación [COLOR_HIGHLIGHT_TEXT]Mining Inc.[COLOR_REVERT], que consume [COLOR_HIGHLIGHT_TEXT]Aluminio[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Hierro[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Cobre[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Carbón[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Plata[COLOR_REVERT] u [COLOR_HIGHLIGHT_TEXT]Oro[COLOR_REVERT] y suma una bonificación a la producción en toda ciudad donde la corporación esté presente. La sede proporcionará oro para todas las ciudades del mundo en las que esté presente la franquicia Mining Inc.. + + + TXT_KEY_BUILDING_CORPORATION_6_STRATEGY + Build the [COLOR_BUILDING_TEXT]Aluminum Co.[COLOR_REVERT] Headquarters to create the [COLOR_HIGHLIGHT_TEXT]Aluminum Co. Corporation[COLOR_REVERT], which consumes [COLOR_HIGHLIGHT_TEXT]Coal[COLOR_REVERT] and adds [COLOR_HIGHLIGHT_TEXT]Aluminum[COLOR_REVERT] and a research bonus to every city where the [COLOR_HIGHLIGHT_TEXT]Aluminum Co. Corporation[COLOR_REVERT] is present. The Headquarters provide gold for each city in the world with an Alunimum Co. franchise. + Construisez le siège d'[COLOR_BUILDING_TEXT]Aluminium S.A.[COLOR_REVERT] pour créer la société commerciale [COLOR_HIGHLIGHT_TEXT]Aluminium S.A.[COLOR_REVERT], qui consomme du [COLOR_HIGHLIGHT_TEXT]charbon[COLOR_REVERT] et génère de l'[COLOR_HIGHLIGHT_TEXT]aluminium[COLOR_REVERT] dans chaque ville où [COLOR_HIGHLIGHT_TEXT]Aluminium S.A.[COLOR_REVERT] est présente. Il confère également un bonus d'or pour chaque ville où se trouve une filiale d'Aluminium S.A. + Der Bau des Unternehmenssitzes der [COLOR_BUILDING_TEXT]Aluminum Co.[COLOR_REVERT] bildet die Grundlage für die Errichtung der Kapitalgesellschaft [COLOR_HIGHLIGHT_TEXT]Aluminum Co.[COLOR_REVERT], welche [COLOR_HIGHLIGHT_TEXT]Kohle[COLOR_REVERT] verarbeitet. Die [COLOR_HIGHLIGHT_TEXT]Aluminum Co.[COLOR_REVERT] versorgt jede Stadt, in der sie vertreten ist, mit [COLOR_HIGHLIGHT_TEXT]Aluminium[COLOR_REVERT] und einem Forschungsbonus. Der Unternehmenssitz bringt allen Städten der Welt mit einem Aluminum Co.-Franchise Gold ein. + Costruisci il Quartier generale della [COLOR_BUILDING_TEXT]Alluminio Co.[COLOR_REVERT] per creare la [COLOR_HIGHLIGHT_TEXT]Corporazione Alluminio Co.[COLOR_REVERT], che consuma [COLOR_HIGHLIGHT_TEXT]Carbone[COLOR_REVERT] e aggiunge [COLOR_HIGHLIGHT_TEXT]Alluminio[COLOR_REVERT] e un bonus sulla ricerca in ogni città in cui si trova. Il Quartier generale fornisce oro in ciascuna città e nel mondo dove è presente la Alluminio Co. + Construye la sede de la [COLOR_BUILDING_TEXT]Aluminum Co.[COLOR_REVERT] para crear la [COLOR_HIGHLIGHT_TEXT]Corporación Aluminum Co. [COLOR_REVERT], que consume [COLOR_HIGHLIGHT_TEXT]Carbón[COLOR_REVERT] y suma [COLOR_HIGHLIGHT_TEXT]Aluminio[COLOR_REVERT] y una bonificación de investigación en toda ciudad donde la corporación esté presente. La sede proporcionará oro para todas las ciudades del mundo en las que esté presente la franquicia Aluminum Co. + + + TXT_KEY_BUILDING_CORPORATION_7_STRATEGY + Build the [COLOR_BUILDING_TEXT]Civilized Jewelers Inc[COLOR_REVERT] Headquarters to create the [COLOR_HIGHLIGHT_TEXT]Civilized Jewelers Inc Corporation[COLOR_REVERT] which consumes [COLOR_HIGHLIGHT_TEXT]Gold[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Silver[COLOR_REVERT] or [COLOR_HIGHLIGHT_TEXT]Gems[COLOR_REVERT] and adds gold and a culture bonus to every city where the [COLOR_HIGHLIGHT_TEXT]Civilized Jewelers Inc Corporation[COLOR_REVERT] is present. The Headquarters provide gold for each city in the world with a Civilized Jewelers franchise. + Construisez le siège des [COLOR_BUILDING_TEXT]Bijoutiers associés[COLOR_REVERT] pour créer la société commerciale [COLOR_HIGHLIGHT_TEXT]Bijoutiers associés[COLOR_REVERT] qui consomme de l'[COLOR_HIGHLIGHT_TEXT]or[COLOR_REVERT], de l'[COLOR_HIGHLIGHT_TEXT]argent[COLOR_REVERT] ou des [COLOR_HIGHLIGHT_TEXT]pierres précieuses[COLOR_REVERT] et confère un bonus d'or à chaque cité où les [COLOR_HIGHLIGHT_TEXT]Bijoutiers associés[COLOR_REVERT] sont présents. Il confère également un bonus d'or pour chaque ville où se trouve une filiale de Bijoutiers associés. + Der Bau des Unternehmenssitzes der [COLOR_BUILDING_TEXT]Civilized Jewelers Inc.[COLOR_REVERT] bildet die Grundlage für die Errichtung der Kapitalgesellschaft [COLOR_HIGHLIGHT_TEXT]Civilized Jewelers Inc.[COLOR_REVERT], welche [COLOR_HIGHLIGHT_TEXT]Gold[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Silber[COLOR_REVERT] oder [COLOR_HIGHLIGHT_TEXT]Edelsteine[COLOR_REVERT] verarbeitet. Die [COLOR_HIGHLIGHT_TEXT]Civilized Jewelers Inc.[COLOR_REVERT] gewährt jeder Stadt, in der sie vertreten ist, einen Kultur- sowie einen Goldbonus. Der Unternehmenssitz bringt allen Städten der Welt mit einem Civilized Jewelers-Franchise Gold ein. + Costruisci il Quartier generale della [COLOR_BUILDING_TEXT]Gioiellieri Civilizzati[COLOR_REVERT] per creare la [COLOR_HIGHLIGHT_TEXT]Corporazione Gioiellieri Civilizzati[COLOR_REVERT], che consuma [COLOR_HIGHLIGHT_TEXT]Oro[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Argento[COLOR_REVERT] o [COLOR_HIGHLIGHT_TEXT]Gemme[COLOR_REVERT] e dà un bonus di cultura e oro in ogni città in cui si trova. Il Quartier generale fornisce oro in ciascuna città dove è presente la Gioiellieri Civilizzati. + Construye la sede de la [COLOR_BUILDING_TEXT]Civilized Jewelers Inc.[COLOR_REVERT] para crear la [COLOR_HIGHLIGHT_TEXT]Corporación Civilized Jewelers Inc.[COLOR_REVERT], que consume [COLOR_HIGHLIGHT_TEXT]Oro[COLOR_REVERT], [COLOR_HIGHLIGHT_TEXT]Plata[COLOR_REVERT] o [COLOR_HIGHLIGHT_TEXT]Gemas[COLOR_REVERT] y suma oro y una bonificación a la cultura de toda ciudad donde la corporación esté presente. La sede proporcionará oro para todas las ciudades del mundo en las que esté presente la franquicia Civilized Jewelers Inc. + + + TXT_KEY_CONCEPT_GOLDEN_AGE_PEDIA + [H1]Golden Ages[\H1][PARAGRAPH:2]During certain periods of time, some civilizations seem to burst with energy and creativity. The civilization's people become increasingly productive; technological advances come easy to the civilization; and its culture is the envy of the world. Italy during the Renaissance is one such example, and Great Britain in the 19th century another. In Civilization IV, such periods are called "golden ages."[PARAGRAPH:2][H2]Entering a Golden Age[\H2][PARAGRAPH:2][BOLD]Wonders:[\BOLD] A civilization can enter a golden age by constructing the [LINK=BUILDING_TAJ_MAHAL]Taj Mahal[\LINK] wonder.[PARAGRAPH:2] [BOLD]Great People:[\BOLD] A civilization can combine one or more [LINK=CONCEPT_GREAT_PEOPLE]Great People[\LINK] of different types to start a golden age. The cost of this method escalates: the first golden age costs one great person, the second costs two, the third one cost three, and so on.[PARAGRAPH:2][H2]Effects of Golden Ages[\H2][PARAGRAPH:2]During a golden age, your civilization greatly increases its output of production and commerce, meaning faster build times and research rates. (In game terms, every space within your cities' radii that provides commerce produces an extra commerce, and every space that provides production now produces an additional one.) In addition, you do not suffer anarchy from Civics and Religion changes, and you generate Great People at a higher rate. [PARAGRAPH:2][H2]Duration of Golden Ages[\H2][PARAGRAPH:2]Golden ages last eight turns on Normal Speed. If you achieve another golden age while in the midst of one already, the eight additional turns are tacked onto the end of the present golden age. You may increase the length of your Golden Ages by controlling the [LINK=BUILDING_MAUSOLEUM_OF_MAUSSOLLOS]Mausoleum of Maussollos[\LINK].[PARAGRAPH:2][H2]The End of the Age[\H2][PARAGRAPH:2]Once the golden age ends, your civilization's commerce and production return to normal levels.[PARAGRAPH:2] + [H1]Age d'or[\H1][PARAGRAPH:2]Il arrive que les civilisations connaissent des périodes durant lesquelles leur énergie et leur créativité atteignent des sommets. La population devient particulièrement productive, le progrès technologique s'accélère et la culture rayonne sur les autres civilisations. L'Italie a connu une telle période au cours de sa Renaissance, ou encore la Grande-Bretagne au XIXe siècle. Ces périodes sont baptisées dans Civilization IV les "Ages d'or".[PARAGRAPH:2][H2]Entrer dans un Age d'Or[\H2][PARAGRAPH:2][BOLD]Merveilles :[\BOLD] une civilisation peut connaître un Age d'or en construisant la merveille [LINK=TAJ_MAHAL]Taj Mahal[\LINK].[PARAGRAPH:2] [BOLD]Personnages illustres : [\BOLD]une civilisation peut sacrifier un [LINK=CONCEPT_GREAT_PEOPLE]personnage illustre[\LINK], ou davantage, pour entrer dans un Age d'or. Le coût de cette méthode tend à augmenter : le premier âge d'or coûte un personnage illustre, le deuxième en coûte deux, le troisième en coûte trois, etc. [PARAGRAPH:2][H2]Effets de l'Age d'or[\H2][PARAGRAPH:2]L'Age d'or améliore considérablement la production et le commerce de la civilisation, ce qui signifie qu'elle construit plus vite et que sa recherche est accélérée (cela se traduit dans le jeu par une unité supplémentaire de commerce par case de terrain exploitée produisant déjà du commerce. Il en est de même pour la production). De plus, les changements de doctrine et de religion n'entraînent aucune période d'anarchie et vous générez plus rapidement des personnages illustres.[PARAGRAPH:2][H2]Durée de l'Age d'or[\H2][PARAGRAPH:2]Un Age d'or dure huit tours à vitesse normale. Si vous atteignez un nouvel Age d'or avant la fin du précédent, les huit tours s'additionnent à ceux du précédent. Vous pouvez contrôler la durée de vos Ages d'or grâce au [LINK=BUILDING_MAUSOLEUM_OF_MAUSSOLLOS]Mausolée d'Halicarnasse[\LINK].[PARAGRAPH:2][H2]La fin d'un Age d'or[\H2][PARAGRAPH:2]Une fois l'Age d'or terminé, le commerce et la production de votre civilisation reviennent à leur (pathétique) niveau normal.[PARAGRAPH:2] + [H1]Goldene Zeitalter[\H1][PARAGRAPH:2]In bestimmten Zeitabschnitten ist die Energie und Kreativität einiger Zivilisationen besonders groß. Ist dies der Fall, entwickelt die Bevölkerung der entsprechenden Zivilisationen eine außergewöhnliche Produktivität. Technische Fortschritte werden dadurch mühelos realisiert und alle Welt staunt über die Kultur der Zivilisation. Typische Beispiele für dieses Phänomen sind Italien (während der Renaissance) und Großbritannien (im 19. Jahrhundert). In Civilization IV bezeichen wir derartige Epochen als "Goldene Zeitalter".[PARAGRAPH:2][H2]Beginn eines Goldenen Zeitalters[\H2][PARAGRAPH:2][BOLD]Wunder:[\BOLD] Eine Zivilisation kann ein Goldenes Zeitalter durch den Bau des [LINK=BUILDING_TAJ_MAHAL]Taj Mahal[\LINK] einleiten.[PARAGRAPH:2] [BOLD]Große Persönlichkeiten:[\BOLD] Eine Zivilisation kann verschiedene Typen [LINK=CONCEPT_GREAT_PEOPLE]Großer Persönlichkeiten[\LINK] kombinieren, um ein Goldenes Zeitalter einzuleiten. Die Kosten sind dabei kumulativ: Das erste Goldene Zeitalter kostet eine Große Persönlichkeit, das zweite kostet zwei, das dritte kostet drei und so fort.[PARAGRAPH:2][H2]Auswirkungen eines Goldenen Zeitalters[\H2][PARAGRAPH:2]Während eines Goldenen Zeitalters erleben die Produktion und die Wirtschaft Ihrer Zivilisation einen bemerkenswerten Aufschwung. Dadurch können Sie deutlich schneller bauen und forschen. (Geländefelder innerhalb des Stadtgebiets, die zum Wirtschaftsertrag beitragen, sind noch produktiver. Geländefelder mit aktiver Produktion produzieren eine zusätzliche Einheit.) Darüber hinaus droht Ihnen keine Anarchie bei Staatsform- und Religionsänderungen und Sie erzeugen schneller Große Persönlichkeiten.[PARAGRAPH:2][H2]Dauer des Goldenen Zeitalters[\H2][PARAGRAPH:2]Ein Goldenes Zeitalter dauert acht Runden bei normaler Spielgeschwindigkeit. Leiten Sie in dieser Zeit ein weiteres Goldenes Zeitalter ein, werden die acht Runden an das Ende des laufenden Zeitalters gehängt. Wenn Sie über das [LINK=BUILDING_MAUSOLEUM_OF_MAUSSOLLOS]Mausoleum von Halikarnassos[\LINK] verfügen, können Sie die Dauer Ihrer Goldenen Zeitalter beeinflussen.[H2]Ende des Zeitalters[\H2][PARAGRAPH:2]Endet ein Goldenes Zeitalter, fallen Wirtschaft und Produktion der Zivilisation auf ihre normalen Werte zurück.[PARAGRAPH:2] + [H1]Ere dell'oro[\H1][PARAGRAPH:2]Nel corso di alcune epoche storiche, sembra che alcune civiltà abbiano avuto un'impennata di energia e creatività. La popolazione è diventata via via più produttiva, i progressi tecnologici si sono susseguiti a ritmo serrato, e la loro cultura è stata invidiata da tutto il mondo. Un esempio è l'Italia del Rinascimento, o la Gran Bretagna nel XIX secolo. In Civilization IV, questi periodi sono chiamati "età dell'oro".[PARAGRAPH:2][H2]Entrare nell'Età dell'Oro[\H2][PARAGRAPH:2][BOLD]Meraviglie:[\BOLD] una civiltà può entrare nell'Età dell'oro costruendo il [LINK=BUILDING_TAJ_MAHAL]Taj Mahal[\LINK].[PARAGRAPH:2] [BOLD]Grande Personaggio:[\BOLD] Una civiltà può sacrificare uno o più [LINK=CONCEPT_GREAT_PEOPLE]Grandi Personaggi[\LINK] di differenti tipi per iniziare un'età dell'oro. Il costo di questa scelta si intensifica via via: la prima età dell'oro costa un Grande Personaggio, la seconda due, la terza tre, e così via.[PARAGRAPH:2][H2]Effetti dell'Età dell'Oro[\H2][PARAGRAPH:2]Nel corso di una età dell'oro, la tua civiltà aumenta la produzione e il commercio, il che significa tempi di costruzione e di ricerca più rapidi. In termini di gioco, ogni casella all'interno del raggio d'azione della città che genera commercio produce un punto commercio aggiuntivo, e ogni casella che produce genera un punto produzione in più. Inoltre, non c'è anarchia durante un cambio di forma di governo o di religione e i Grandi Personaggi nascono più rapidamente. [PARAGRAPH:2][H2]Durata dell'Età dell'Oro[\H2][PARAGRAPH:2]Le età dell'oro durano otto turni alla velocità normale. Se riesci ad entrare in un'altra età dell'oro mentre una è ancora in svolgimento, vengono aggiunti altri otto turni a quella corrente (il che significa che due età dell'oro durano - combinate - sedici turni). Puoi aumentare la durata delle tue età dell'oro controllando il [LINK=BUILDING_MAUSOLEUM_OF_MAUSSOLLOS]Mausoleo di Mausolo[\LINK].[PARAGRAPH:2][H2]Termine dell'Età dell'Oro[\H2][PARAGRAPH:2]Una volta finita l'età dell'oro, il commercio e la produzione della tua civiltà ritornano ai livelli normali.[PARAGRAPH:2] + [H1]Edades de oro[\H1][PARAGRAPH:2]Durante ciertos periodos, algunas civilizaciones parecen rebosar de energía y creatividad. Ese pueblo se hace cada vez más productivo, los avances tecnológicos son más fáciles para esa civilización y su cultura es la envidia de todo el mundo. Un par de ejemplos serían Italia durante el Renacimiento y Gran Bretaña durante el s. XIX. En Civilization IV, a tales periodos se los denomina "edades de oro".[PARAGRAPH:2][H2]Entrar en una edad de oro[\H2][PARAGRAPH:2][BOLD]Maravillas:[\BOLD] Una civilización puede entrar en una edad de oro si construye la maravilla del [LINK=BUILDING_TAJ_MAHAL]Taj Mahal[\LINK].[PARAGRAPH:2] [BOLD]Sacrificar a grandes personajes:[\BOLD] Una civilización puede sacrificar uno o más [LINK=CONCEPT_GREAT_PEOPLE]grandes personajes[\LINK] de distintos tipos para entrar en una edad de oro. El coste de este método va en aumento: la primera edad de oro cuesta un gran personaje; la segunda, dos; la tercera, tres; y así sucesivamente.[PARAGRAPH:2][H2]Efectos de las edades de oro[\H2][PARAGRAPH:2]Durante una edad de oro, la civilización aumentará intensamente sus regímenes de producción y comercio, lo que supone mayor velocidad en la construcción y la investigación (en términos de juego: cada casilla que esté dentro del radio urbano de tus ciudades y que proporcione comercio dará uno más de comercio y cada casilla que proporcione producción pasará a producir uno más). Además, no sufrirás la anarquía por los cambios de principios o de religión, y generarás grandes personajes a más velocidad. [PARAGRAPH:2][H2]Duración de las edades de oro[\H2][PARAGRAPH:2]Las edades de oro duran ocho turnos a velocidad Normal. Si logras otra edad de oro mientras estés en medio de una, los ocho turnos adicionales enlazarán con el final de la edad de oro presente. Puedes aumentar la duración de tus edades de oro si controlas el [LINK=BUILDING_MAUSOLEUM_OF_MAUSSOLLOS]Mausoleo de Mausolo[\LINK].[PARAGRAPH:2][H2]El fin de la edad[\H2][PARAGRAPH:2]Cuando una edad de oro termine, el comercio y la producción de tu civilización volverán a sus niveles normales (y patéticos).[PARAGRAPH:2] + + + TXT_KEY_BUILDING_MT_RUSHMORE_STRATEGY + [COLOR_BUILDING_TEXT]Mount Rushmore[COLOR_REVERT] decreases war weariness in all cities in your civilization and increases its city's chances of generating a [COLOR_UNIT_TEXT]Great Artist[COLOR_REVERT]. + Le [COLOR_BUILDING_TEXT]mont Rushmore[COLOR_REVERT] réduit le mécontentement dû à la guerre dans toutes les villes de votre civilisation et augmente les chances d'apparition d'un [COLOR_UNIT_TEXT]artiste illustre[COLOR_REVERT]. + Der [COLOR_BUILDING_TEXT]Mount Rushmore[COLOR_REVERT]verringert in allen Städten Ihrer Zivilisation die Kriegsmüdigkeit und erhöht die Chancen der jeweiligen Stadt, einen [COLOR_UNIT_TEXT]Großen Künstler[COLOR_REVERT] hervorzubringen. + I [COLOR_BUILDING_TEXT]Monti Rushmore[COLOR_REVERT] riducono la stanchezza della guerra in tutte le città della tua civiltà e aumentano la probabilità di generare un [COLOR_UNIT_TEXT]Grande Artista[COLOR_REVERT]. + El [COLOR_BUILDING_TEXT]Monte Rushmore[COLOR_REVERT] disminuye el hastío bélico en todas las ciudades de la civilización y aumenta las posibilidades de que en su ciudad se genere un [COLOR_UNIT_TEXT]Gran artista[COLOR_REVERT]. + + + TXT_KEY_MISSION_SENTRY_HELP + The unit remains inactive until an enemy unit enters its visibility range. + L'unité reste inactive tant qu'une unité ennemie ne pénètre pas dans son champ de vision. + Die Einheit bleibt inaktiv, bis eine feindliche Einheit in Sichtweite ist. + L'unità rimane inattiva finché un'unità nemica non diventa visibile. + La unidad permanecerá inactiva hasta que una unidad enemiga se sitúe al alcance de la visibilidad. + + + TXT_KEY_CONCEPT_FORT_PEDIA + [H1]Updated Forts[\H1][PARAGRAPH:2]Forts have been significantly updated since the initial release of Civilization IV. Forts can now be built outside of your borders and function in many ways as cities. Units attacking or defending Forts will make use of their city-related promotions, so long as the units inside the Fort are in friendly or neutral territory.[PARAGRAPH:1]Forts within your cultural boundaries also act as port cities for ships, meaning that ships can heal in them, but also that Forts can be used to form canals, up to two tiles wide, through which ships can cross. They also act as ports when determining trade connections. They can also now be used to connect to resources within your cultural boundaries. Finally, Forts can be used as bases for air units and offer the increased heal rate usually only available within city boundaries. These last two abilities make them excellent launching pads for operations into enemy territory. + [H1]Forts mis à jour[\H1][PARAGRAPH:2]Les forts ont été largement remaniés depuis la sortie initiale de Civilization IV. Les forts peuvent à présent être construits en dehors de vos frontières et fonctionnent sensiblement comme les villes. Les unités défendant les forts utiliseront leurs promotions relatives à leur ville, tant que les unités dans le fort sont en territoire ami ou neutre.[PARAGRAPH:1]Les forts situés dans vos frontières culturelles font également office de villes portuaires pour les navires, qui peuvent s'y soigner. Ils font office de port lors de mise en place de liens commerciaux et permettent à présent être utilisés pour faire circuler des ressources à l'intérieur de votre zone d'influence culturelle. Enfin, les forts peuvent aussi former des canaux jusqu'à 2 cases de largeur, que les navires peuvent utiliser et peuvent servir de base aux unités aériennes et offrent un taux de guérison qui est d'habitude seulement disponible dans les villes. Ces deux dernières compétences en font d'excellentes plateformes de lancement pour les opérations en territoire ennemi. + [H1]Verbesserte Festungen[\H1][PARAGRAPH:2]Festungen wurden seit der ursprünglichen Veröffentlichung von Civilization IV deutlich verbessert. Festungen können nun außerhalb Ihrer Grenzen errichtet werden und sind Städten in vielen Dingen ähnlich. Einheiten, die Festungen angreifen oder verteidigen, ziehen Vorteile aus ihren stadtbezogenen Beförderungen, solange sich die Einheiten innerhalb der Festung auf freundlichem oder neutralem Gebiet befinden.[PARAGRAPH:1]Festungen dienen auch als Hafenstädte für Schiffe, d. h. Schiffe darin werden repariert, und sie können dazu benutzt werden, bis zu zwei Geländefelder breite Kanäle zu bilden, über die Schiffe queren können. Sie können beim Festlegen der Handelswege als Häfen fungieren und dazu eingesetzt werden, Zugang zu Ressourcen innerhalb Ihrer kulturellen Grenzen zu erlangen. Festungen können außerdem als Basis für Lufteinheiten verwendet werden und bieten die gesteigerte Heilungsrate, die normalerweise nur innerhalb der Stadtgrenzen verfügbar ist. Diese letzten beiden Fähigkeiten machen Festungen zu ausgezeichneten Ausgangspunkten für Angriffe auf feindliches Gebiet. + [H1]Forti aggiornati[\H1][PARAGRAPH:2]I forti sono stati notevolmente migliorati dalla prima versione di Civilization IV. Adesso possono essere costruiti al di fuori dei tuoi confini, e per molti versi funzionano come le città. Le unità che difendono i forti potranno usare le proprie promozioni, almeno fin quando le unità dentro il forte si trovano in territorio amico o neutrale.[PARAGRAPH:1]I forti all'interno dei tuoi confini culturali possono anche fungere da città portuali per le navi, il che significa che possono curarsi, ma anche che possono essere usati per costruire canali, larghi fino a due caselle, lungo cui possono passare le navi. Possono anche fungere da porto quando si creano collegamenti commerciali. Possono essere usati per collegare risorse all'interno dei tuoi confini culturali. Per finire, i forti possono essere usati come basi per le unità aeree, e fornire il tasso di guarigione solitamente disponibile all'interno dei confini cittadini. Queste ultime due abilità li rendono ottime piattaforme di lancio per operazioni in territorio nemico. + [H1]Fuertes actualizados[\H1][PARAGRAPH:2]Los fuertes han cambiado significativamente desde la primera entrega de Civilization IV. Ahora pueden construirse fuera de las fronteras y funcionan de modo parecido a las ciudades en muchos aspectos. Las unidades que defiendan fuertes harán uso de los ascensos relativos a sus ciudades siempre y cuando el fuerte en el que estén se encuentre en territorio amigo o neutral.[PARAGRAPH:1]Los fuertes situados dentro de tus fronteras culturales también funcionan como ciudades portuarias para los barcos, lo cual significa que éstos pueden repararse allí, pero también que los fuertes pueden utilizarse para formar canales de hasta dos casillas de ancho que pueden cruzar los barcos. También funcionan como puertos a la hora de determinar relaciones comerciales. Ahora, además pueden emplearse para llegar a los recursos que estén dentro de tus fronteras culturales. Por último, se pueden usar como bases para las unidades aéreas y ofrecer la velocidad de curación aumentada que solo suele estar disponible dentro de los límites de una ciudad. Estas dos últimas capacidades los convierten en unas plataformas de lanzamiento excelentes para las operaciones en territorio enemigo. + + + TXT_KEY_CONCEPT_EVENTS_PEDIA + [H1]Events[\H1][PARAGRAPH:2]Special Events now occur at random intervals throughout the game, allowing the player to demonstrate the type of ruler they wish to be. The dozens of events in Beyond the Sword may range from requiring the player to decide how to deal with a bandit gang to cleaning up after a plane crash, but will usually be tied to the player's in-game decisions. It will be impossible for a player to experience a slave revolt if the player does not use the Slavery civic. How the player handles each event will decide the rewards and attitude changes for those involved.[PARAGRAPH:1]Events are divided into two main types - Occurrences and Quests. Occurrences require the player to make an on-the-fly decision, the results of which take immediate effect. Quests require the player to complete a certain objective in order to receive a reward. But be sure to hurry, as many quests will be given to multiple Civilizations, meaning the first to complete it will garner the benefits. [NEWLINE]You may view your active Quests on the Log Screen [CTRL + TAB][PARAGRAPH:1]Events can be disabled by starting a "Custom Game" and selecting the "No Random Events" Option. + [H1]Evénements[\H1][PARAGRAPH:2]Des événements spéciaux se produisent désormais aléatoirement. Ils sont l'occasion pour vous de montrer quel genre de chef vous voulez être. Les dizaines d'événements de Beyond the Sword sont très variés. Vous pouvez avoir à décider comment neutraliser un gang de bandits, ou comment faire le ménage après une catastrophe aérienne. Toutefois, ces événements dépendront généralement de vos décisions. Vous ne pourrez pas être confronté à une révolte d'esclaves, par exemple, si vous ne pratiquez pas l'esclavage. Votre façon de gérer chaque événement déterminera vos récompenses et le comportement des groupes impliqués.[PARAGRAPH:1]Il y a deux sortes d'événements : les crises et les quêtes. Les crises vous obligeront à prendre une décision au pied levé et ses effets se feront sentir immédiatement. Les quêtes vous obligeront à accomplir un objectif pour obtenir une récompense. Vous devrez les accomplir sans tarder, car les quêtes peuvent être confiées à plusieurs civilisations, et seule la première à l'accomplir sera récompensée.[NEWLINE]Vous pouvez afficher vos quêtes actives sur l'écran Journal[CTRL + TAB][PARAGRAPH:1]Vous pouvez désactiver les événements en commençant une partie personnalisée et en sélectionnant l'option "Pas d'événements aléatoires". + [H1]Ereignisse[\H1][PARAGRAPH:2]Im Laufe des Spiels finden in zufälligen Intervallen besondere Ereignisse statt, die den Spielern Gelegenheit bieten, ihren Charakter als Staatsoberhaupt zu festigen. So muss während der zahlreichen Ereignisse in Beyond The Sword beispielsweise entschieden werden, auf welche Art mit Banditen umgegangen oder nach einem Flugzeugabsturz vorgegangen werden soll, im Allgemeinen orientieren sich die Ereignisse jedoch an den vorherigen Handlungen und Entscheidungen des Spielers - demzufolge ist es auch nicht möglich, dass ein Spieler mit einem Sklavenaufstand konfrontiert wird, wenn er die Staatsform "Sklaverei" gar nicht verwendet. Wie die betroffenen Parteien belohnt werden und inwiefern sich ihre Haltung ändert, ist davon abhängig, wie sich ein Spieler bei jedem einzelnen Ereignis verhält.[PARAGRAPH:1]Es werden zwei grundlegende Arten von Ereignissen unterschieden: Vorfälle und Quests. Vorfälle fordern dem Spieler eine spontane Entscheidung ab, die ummittelbare Auswirkungen zeigt. Bei den Quests muss der Spieler eine bestimmte Zielsetzung erfüllen, und das möglichst schnell, denn viele Quests werden mehreren Zivilisationen gleichzeitig gestellt, aber nur die Nation, die das Ziel als Erste erreicht, erhält die damit verbundene Belohnung.[NEWLINE]Sie können Ihre aktiven Quests im Log-Bildschirm einsehen [STRG + TAB][PARAGRAPH:1]Um das Auftreten von Ereignissen vollständig zu deaktivieren, starten Sie ein "Eigenes Spiel" und wählen Sie hier die Option "Keine Zufallsereignisse". + [H1]Eventi[\H1][PARAGRAPH:2]Adesso gli eventi speciali si verificano a intervalli casuali durante tutta la partita, permettendo al giocatore di dimostrare le proprie qualità di leader. In Beyond the Sword sono presenti dozzine di eventi che, a seconda delle scelte di gioco, metteranno il giocatore di fronte alle più disparate situazioni: dal decidere come affrontare un gruppo di banditi, alla gestione delle operazioni di ricostruzione dopo un incidente aereo. Infatti, per un giocatore sarà impossibile subire una rivolta di schiavi se non utilizza la forma di governo Schiavismo. In base al comportamento del giocatore di fronte a ogni situazione, verranno determinate le ricompense e i cambiamenti attitudinali verso tutti coloro che sono stati coinvolti.[PARAGRAPH:1]Gli eventi sono divisi in due categorie: avvenimenti e imprese. Gli avvenimenti costringono il giocatore a prendere decisioni immediate, il risultato delle quali avrà effetto immediato. Per realizzare le imprese, il giocatore deve raggiungere un certo obiettivo per ricevere in cambio una ricompensa. Ma fai in fretta, perché altre civiltà potrebbero dover compiere le stesse imprese e arrivare per primi è fondamentale. [NEWLINE]È possibile vedere le missioni attive nel Registro eventi [CTRL + TAB][PARAGRAPH:1]Gli eventi possono essere disattivati iniziando una "Partita personalizzata" e selezionando l'opzione "Nessun evento casuale". + [H1]Sucesos[\H1][PARAGRAPH:2]Los Sucesos especiales ocurren a intervalos aleatorios a lo largo del juego, y permiten al jugador demostrar la clase de mandatario que desea ser. Las docenas de sucesos posibles de Beyond the Sword van desde tener que ocuparse de una banda de salteadores hasta retirar los restos de un accidente aéreo, pero normalmente guardarán alguna relación con las decisiones del jugador durante la partida. Será imposible que el jugador sufra una revuelta de esclavos si no utiliza el principio de la esclavitud. La forma en que el jugador se ocupe de cada suceso determinará las recompensas y cambios de actitud de los implicados.[PARAGRAPH:1]Los sucesos se dividen en dos tipos principales: incidencias y misiones. Las incidencias requieren que el jugador tome una decisión sobre la marcha, cuyos resultados tendrán un efecto inmediato. Las misiones requieren que el jugador complete un determinado objetivo para recibir una recompensa. Pero asegúrate de darte prisa, ya que muchas misiones serán asignadas a varias civilizaciones, de modo que el primero en completarla recogerá sus beneficios. [NEWLINE]Puedes ver tus misiones en activo en la pantalla del historial [CTRL + TAB].[PARAGRAPH:1]Los sucesos pueden desactivarse al elegir "Personalizar partida" si se selecciona la opción "Sin sucesos al azar". + + + TXT_KEY_CITY_NAME_GONDAR + Gondar + Gondar + Gondar + Gondar + Gondar + + + TXT_KEY_CITY_NAME_LUBAANTUM + Lubaantun + Lubaantun + Lubaantun + Lubaantun + Lubaantun + + + TXT_KEY_BTS_TECHS_PEDIA + [H1]Beyond the Sword Technologies[\H1][NEWLINE][LINK=TECH_ADVANCED_FLIGHT]Advanced Flight[\LINK][NEWLINE][NEWLINE][LINK=TECH_AESTHETICS]Aesthetics[\LINK][NEWLINE][NEWLINE][LINK=TECH_LASER]Laser[\LINK][NEWLINE][NEWLINE][LINK=TECH_MILITARY_SCIENCE]Military Science[\LINK][NEWLINE][NEWLINE][LINK=TECH_STEALTH]Stealth[\LINK][NEWLINE][NEWLINE][LINK=TECH_SUPERCONDUCTORS]Superconductors[\LINK] + H1]Technologies de Beyond the Sword[\H1][NEWLINE][LINK=TECH_ADVANCED_FLIGHT]Aviation avancée[\LINK][NEWLINE][NEWLINE][LINK=TECH_AESTHETICS]Esthétique[\LINK][NEWLINE][NEWLINE][LINK=TECH_LASER]Laser[\LINK][NEWLINE][NEWLINE][LINK=TECH_MILITARY_SCIENCE]Science militaire[\LINK][NEWLINE][NEWLINE][LINK=TECH_STEALTH]Furtivité[\LINK][NEWLINE][NEWLINE][LINK=TECH_SUPERCONDUCTORS]Supraconducteurs[\LINK] + [H1]Technologien in Beyond the Sword[\H1][NEWLINE][LINK=TECH_ADVANCED_FLIGHT]Fortgeschrittene Luftfahrt[\LINK][NEWLINE][NEWLINE][LINK=TECH_AESTHETICS]Ästhetik[\LINK][NEWLINE][NEWLINE][LINK=TECH_LASER]Laser[\LINK][NEWLINE][NEWLINE][LINK=TECH_MILITARY_SCIENCE]Militärwissenschaft[\LINK][NEWLINE][NEWLINE][LINK=TECH_STEALTH]Tarnung[\LINK][NEWLINE][NEWLINE][LINK=TECH_SUPERCONDUCTORS]Supraleiter[\LINK] + [H1]Tecnologie di Beyond the Sword[\H1][NEWLINE][LINK=TECH_ADVANCED_FLIGHT]Volo avanzato[\LINK][NEWLINE][NEWLINE][LINK=TECH_AESTHETICS]Estetica[\LINK][NEWLINE][NEWLINE][LINK=TECH_LASER]Laser[\LINK][NEWLINE][NEWLINE][LINK=TECH_MILITARY_SCIENCE]Scienza militare[\LINK][NEWLINE][NEWLINE][LINK=TECH_STEALTH]Invisibilità[\LINK][NEWLINE][NEWLINE][LINK=TECH_SUPERCONDUCTORS]Superconduttori[\LINK] + [H1]Tecnologías de "Beyond The Sword"[\H1][NEWLINE][LINK=TECH_ADVANCED_FLIGHT]Vuelo avanzado[\LINK][NEWLINE][NEWLINE][LINK=TECH_AESTHETICS]Estética[\LINK][NEWLINE][NEWLINE][LINK=TECH_LASER]Láser[\LINK][NEWLINE][NEWLINE][LINK=TECH_MILITARY_SCIENCE]Belicología[\LINK][NEWLINE][NEWLINE][LINK=TECH_STEALTH]Invisibilidad ante el radar[\LINK][NEWLINE][NEWLINE][LINK=TECH_SUPERCONDUCTORS]Superconductores[\LINK] + + + TXT_KEY_BTS_LEADERS_PEDIA + [H1]Beyond the Sword Leaders[\H1][NEWLINE][LINK=LEADER_BOUDICA]Boudica[\LINK][NEWLINE][NEWLINE][LINK=LEADER_CHARLEMAGNE]Charlemagne[\LINK][NEWLINE][NEWLINE][LINK=LEADER_DARIUS]Darius I[\LINK][NEWLINE][NEWLINE][LINK=LEADER_DE_GAULLE]Charles de Gaulle[\LINK][NEWLINE][NEWLINE][LINK=LEADER_GILGAMESH]Gilgamesh[\LINK][NEWLINE][NEWLINE][LINK=LEADER_HAMMURABI]Hammurabi[\LINK][NEWLINE][NEWLINE][LINK=LEADER_JOAO]Joao II[\LINK][NEWLINE][NEWLINE][LINK=LEADER_JUSTINIAN]Justinian[\LINK][NEWLINE][NEWLINE][LINK=LEADER_LINCOLN]Abraham Lincoln[\LINK][NEWLINE][NEWLINE][LINK=LEADER_PACAL]Pacal[\LINK][NEWLINE][NEWLINE][LINK=LEADER_PERICLES]Pericles[\LINK][NEWLINE][NEWLINE][LINK=LEADER_SITTING_BULL]Sitting Bull[\LINK][NEWLINE][NEWLINE][LINK=LEADER_SULEIMAN]Suleiman[\LINK][NEWLINE][NEWLINE][LINK=LEADER_SURYAVARMAN]Suryavarman II[\LINK][NEWLINE][NEWLINE][LINK=LEADER_WILLEM_VAN_ORANJE]Willem van Oranje[\LINK][NEWLINE][NEWLINE][LINK=LEADER_ZARA_YAQOB]Zara Yaqob[\LINK][NEWLINE][NEWLINE] + [H1]Dirigeants de Beyond the Sword[\H1][NEWLINE][LINK=LEADER_BOUDICA]Boadicée[\LINK][NEWLINE][NEWLINE][LINK=LEADER_CHARLEMAGNE]Charlemagne[\LINK][NEWLINE][NEWLINE][LINK=LEADER_DARIUS]Darius I[\LINK][NEWLINE][NEWLINE][LINK=LEADER_DE_GAULLE]Charles de Gaulle[\LINK][NEWLINE][NEWLINE][LINK=LEADER_GILGAMESH]Gilgamesh[\LINK][NEWLINE][NEWLINE][LINK=LEADER_HAMMURABI]Hammurabi[\LINK][NEWLINE][NEWLINE][LINK=LEADER_JOAO]Joao II[\LINK][NEWLINE][NEWLINE][LINK=LEADER_JUSTINIAN]Justinien I[\LINK][NEWLINE][NEWLINE][LINK=LEADER_LINCOLN]Abraham Lincoln[\LINK][NEWLINE][NEWLINE][LINK=LEADER_PACAL]Pacal II[\LINK][NEWLINE][NEWLINE][LINK=LEADER_PERICLES]Périclès[\LINK][NEWLINE][NEWLINE][LINK=LEADER_SITTING_BULL]Sitting Bull[\LINK][NEWLINE][NEWLINE][LINK=LEADER_SULEIMAN]Soliman[\LINK][NEWLINE][NEWLINE][LINK=LEADER_SURYAVARMAN]Sûryavarman II[\LINK][NEWLINE][NEWLINE][LINK=LEADER_WILLEM_VAN_ORANJE]Guillaume d'Orange[\LINK][NEWLINE][NEWLINE][LINK=LEADER_ZARA_YAQOB]Zara Yacoub[\LINK][NEWLINE][NEWLINE] + [H1]Staatsoberhäupter in Beyond the Sword [\H1][NEWLINE][LINK=LEADER_BOUDICA]Boudicca[\LINK][NEWLINE][NEWLINE][LINK=LEADER_CHARLEMAGNE]Karl der Große[\LINK][NEWLINE][NEWLINE][LINK=LEADER_DARIUS]Dareios I.[\LINK][NEWLINE][NEWLINE][LINK=LEADER_DE_GAULLE]Charles de Gaulle[\LINK][NEWLINE][NEWLINE][LINK=LEADER_GILGAMESH]Gilgamesch[\LINK][NEWLINE][NEWLINE][LINK=LEADER_HAMMURABI]Hammurabi[\LINK][NEWLINE][NEWLINE][LINK=LEADER_JOAO]Joao II.[\LINK][NEWLINE][NEWLINE][LINK=LEADER_JUSTINIAN]Justinian[\LINK][NEWLINE][NEWLINE][LINK=LEADER_LINCOLN]Abraham Lincoln[\LINK][NEWLINE][NEWLINE][LINK=LEADER_PACAL]Pacal II.[\LINK][NEWLINE][NEWLINE][LINK=LEADER_PERICLES]Perikles[\LINK][NEWLINE][NEWLINE][LINK=LEADER_SITTING_BULL]Sitting Bull[\LINK][NEWLINE][NEWLINE][LINK=LEADER_SULEIMAN]Süleyman[\LINK][NEWLINE][NEWLINE][LINK=LEADER_SURYAVARMAN]Suryavarman II.[\LINK][NEWLINE][NEWLINE][LINK=LEADER_WILLEM_VAN_ORANJE]Wilhelm von Oranien[\LINK][NEWLINE][NEWLINE][LINK=LEADER_ZARA_YAQOB]Zara Yaqob[\LINK][NEWLINE][NEWLINE] + [H1]Leader di Beyond the Sword[\H1][NEWLINE][LINK=LEADER_BOUDICA]Boudica[\LINK][NEWLINE][NEWLINE][LINK=LEADER_CHARLEMAGNE]Carlo Magno[\LINK][NEWLINE][NEWLINE][LINK=LEADER_DARIUS]Dario I[\LINK][NEWLINE][NEWLINE][LINK=LEADER_DE_GAULLE]Charles de Gaulle[\LINK][NEWLINE][NEWLINE][LINK=LEADER_GILGAMESH]Gilgamesh[\LINK][NEWLINE][NEWLINE][LINK=LEADER_HAMMURABI]Hammurabi[\LINK][NEWLINE][NEWLINE][LINK=LEADER_JOAO]Giovanni II[\LINK][NEWLINE][NEWLINE][LINK=LEADER_JUSTINIAN]Giustiniano[\LINK][NEWLINE][NEWLINE][LINK=LEADER_LINCOLN]Abramo Lincoln[\LINK][NEWLINE][NEWLINE][LINK=LEADER_PACAL]Pakal[\LINK][NEWLINE][NEWLINE][LINK=LEADER_PERICLES]Pericle[\LINK][NEWLINE][NEWLINE][LINK=LEADER_SITTING_BULL]Toro Seduto[\LINK][NEWLINE][NEWLINE][LINK=LEADER_SULEIMAN]Solimano[\LINK][NEWLINE][NEWLINE][LINK=LEADER_SURYAVARMAN]Suryavarman II[\LINK][NEWLINE][NEWLINE][LINK=LEADER_WILLEM_VAN_ORANJE]Guglielmo d'Orange[\LINK][NEWLINE][NEWLINE][LINK=LEADER_ZARA_YAQOB]Zara Yaqob[\LINK][NEWLINE][NEWLINE] + [H1]Líderes de "Beyond The Sword"[\H1][NEWLINE][LINK=LEADER_BOUDICA]Boadicea[\LINK][NEWLINE][NEWLINE][LINK=LEADER_CHARLEMAGNE]Carlomagno[\LINK][NEWLINE][NEWLINE][LINK=LEADER_DARIUS]Darío I[\LINK][NEWLINE][NEWLINE][LINK=LEADER_DE_GAULLE]Charles de Gaulle[\LINK][NEWLINE][NEWLINE][LINK=LEADER_GILGAMESH]Gilgamesh[\LINK][NEWLINE][NEWLINE][LINK=LEADER_HAMMURABI]Hammurabi[\LINK][NEWLINE][NEWLINE][LINK=LEADER_JOAO]Juan II[\LINK][NEWLINE][NEWLINE][LINK=LEADER_JUSTINIAN]Justiniano I[\LINK][NEWLINE][NEWLINE][LINK=LEADER_LINCOLN]Abraham Lincoln[\LINK][NEWLINE][NEWLINE][LINK=LEADER_PACAL]Pacal II[\LINK][NEWLINE][NEWLINE][LINK=LEADER_PERICLES]Pericles[\LINK][NEWLINE][NEWLINE][LINK=LEADER_SITTING_BULL]Toro Sentado[\LINK][NEWLINE][NEWLINE][LINK=LEADER_SULEIMAN]Solimán[\LINK][NEWLINE][NEWLINE][LINK=LEADER_SURYAVARMAN]Suryavarman II[\LINK][NEWLINE][NEWLINE][LINK=LEADER_WILLEM_VAN_ORANJE]Guillermo de Orange[\LINK][NEWLINE][NEWLINE][LINK=LEADER_ZARA_YAQOB]Zara Yakub[\LINK][NEWLINE][NEWLINE] + + + TXT_KEY_BTS_CIVS_PEDIA + [H1]Beyond the Sword Civilizations[\H1][NEWLINE][LINK=CIVILIZATION_BABYLON]Babylonian Empire[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_BYZANTIUM]Byzantine Empire[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_NETHERLANDS]Dutch Empire[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_ETHIOPIA]Ethiopian Empire[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_HOLY_ROMAN]Holy Roman Empire[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_KHMER]Khmer Empire[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_MAYA]Mayan Empire[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_NATIVE_AMERICA]Native American Empire[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_PORTUGAL]Portuguese Civilization[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_SUMERIA]Sumerian Civilization[\LINK] + H1]Civilisations de Beyond the Sword[\H1][NEWLINE][LINK=CIVILIZATION_BABYLON]Empire babylonien[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_BYZANTIUM]Empire byzantin[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_NETHERLANDS]Empire néerlandais[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_ETHIOPIA]Empire éthiopien [\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_HOLY_ROMAN]Saint Empire romain germanique[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_KHMER]Empire khmer[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_MAYA]Empire maya[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_NATIVE_AMERICA]Empire amérindien[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_PORTUGAL]Civilisation portugaise[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_SUMERIA]Civilisation sumérienne[\LINK] + [H1]Zivilisationen in Beyond the Sword[\H1][NEWLINE][LINK=CIVILIZATION_BABYLON]Babylonisches Reich[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_BYZANTIUM]Byzantinisches Reich[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_NETHERLANDS]Holländisches Reich[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_ETHIOPIA]Äthiopisches Reich[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_HOLY_ROMAN]Heiliges Römisches Reich[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_KHMER]Khmer-Reich[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_MAYA]Mayareich[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_NATIVE_AMERICA]Indianisches Reich[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_PORTUGAL]Portugiesisches Reich[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_SUMERIA]Sumerisches Reich[\LINK] + [H1]Civiltà di Beyond the Sword[\H1][NEWLINE][LINK=CIVILIZATION_BABYLON]Impero babilonese[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_BYZANTIUM]Impero bizantino[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_NETHERLANDS]Impero olandese[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_ETHIOPIA]Impero etiope[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_HOLY_ROMAN]Sacro Romano Impero[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_KHMER]Impero khmer[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_MAYA]Impero maya[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_NATIVE_AMERICA]Impero dei nativi americani[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_PORTUGAL]Civiltà portoghese[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_SUMERIA]Civiltà sumera[\LINK] + [H1]Civilizaciones de "Beyond The Sword"[\H1][NEWLINE][LINK=CIVILIZATION_BABYLON]Imperio Babilonio[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_BYZANTIUM]Imperio Bizantino[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_NETHERLANDS]Imperio Holandés[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_ETHIOPIA]Imperio Etíope[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_HOLY_ROMAN]Sacro Imperio Romano[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_KHMER]Imperio Jémer[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_MAYA]Imperio Maya[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_NATIVE_AMERICA]Imperio Indio Americano[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_PORTUGAL]Imperio Portugués[\LINK][NEWLINE][NEWLINE][LINK=CIVILIZATION_SUMERIA]Imperio Sumerio[\LINK] + + + CHANGED_TXT_KEY_MAIN_MENU_WARLORS + Beyond the Sword Content + Contenu de Beyond the Sword + Beyond The Sword-Inhalte + Contenuti di Beyond the Sword + Contenido de Beyond the Sword + + + TXT_KEY_UNIT_EXECUTIVE_2 + Sid's Sushi Executive + + Dirigeant de Sid's Sushi + Male + 0 + + + Vorstand der Sid's Sushi Co. + Male + 0 + + + Funzionario della Sid Sushi + Male + 0 + + + Ejecutivo de Sid's Sushi:Ejecutivos de Sid's Sushi + Male + 0:1 + + + + CHANGED_TXT_KEY_CORPORATION_2 + Sid's Sushi Co + + Sid's Sushi Co + Male + 0 + + + Sid's Sushi Co. + Male + 0 + + + Sid Sushi + Male + 0 + + + Sid's Sushi + Female + 0 + + + + TXT_KEY_CONCEPT_COLONIES_PEDIA + [H1]Colonies[\H1][PARAGRAPH:2]The maintenance of your cities now takes into account a third factor beyond the number of cities in your civilization and their distance from the capital. This new maintenance cost only affects cities on overseas continents that do not contain your capital. When the number of cities on that distant continent reaches a certain level, maintenance costs will begin to outweigh production.[PARAGRAPH:1]To deal with this loss, the player may turn the cities on an overseas continent into a Colony. By granting those cities Colony status, they will immediately break off into their own, distinct civilization, and become a vassal of the player. They will be run by an AI, but the player will still have access to all the resources of their colony. You may choose to create a Colony from your overseas empire by using the button on the Domestic Advisor screen.[PARAGRAPH:1]Colonies receive a major attitude bonus towards their parent civilization, and so long as relations remain good between the parent civilization and the Colony, the Colony will remain a vassal to them. However, Colonies will not stand for abuse, so if a Colony's attitude towards the parent civilization sours, they may break from their parent completely. Colonies can never be reabsorbed by the parent civilization - they must be conquered if you wish them to again be part of your empire. + [H1]Colonies[\H1][PARAGRAPH:2]L'entretien des villes prend à présent en compte un troisième facteur en plus du nombre de villes de votre civilisation et de la distance avec la capitale. Le coût d'entretien à l'étranger ne s'applique qu'aux villes situées sur les continents qui n'accueillent pas votre capitale. Lorsque vous avez un certain nombre de villes sur un continent lointain, leur coût d'entretien peut commencer à dépasser leur production.[PARAGRAPH:1]Pour faire face à cela, vous devez transformer les villes des continents étrangers en colonies. En leur donnant le statut de colonie, elles créent leur propre civilisation et deviennent vos vassales. Elles sont dirigées par l'IA, mais vous avez toujours accès à toutes les ressources de la colonie. Vous pouvez créer une colonie dans votre empire d'outremer en utilisant le bouton sur l'écran du Conseiller aux affaires intérieures.[PARAGRAPH:1]Les colonies reçoivent un bonus d'attitude important envers leur civilisation mère et, tant qu'elles gardent de bonnes relations avec celle-ci, les colonies restent vassales. Cependant, les colonies ne supportent pas d'être exploitées. Si l'attitude d'une colonie envers sa civilisation mère se dégrade, elle risque de rompre tout contact. Les colonies ne peuvent pas être réabsorbées par leur civilisation mère. Elles doivent être reconquises si vous souhaitez qu'elles refassent partie de votre empire. + [H1]Kolonien[\H1][PARAGRAPH:2]Der Unterhalt Ihrer Städte berücksichtigt jetzt auch einen dritten Faktor außer der Anzahl Städte in Ihrer Zivilisation und deren Entfernung von der Hauptstadt. Diese neuen Unterhaltskosten betreffen nur Städte in Übersee-Kontinenten, auf denen nicht Ihre Hauptstadt liegt. Wenn die Anzahl Städte auf diesem fernen Kontinent eine bestimmte Schwelle überschreitet, sind die Unterhaltskosten höher als der Gewinn durch die Produktion.[PARAGRAPH:1]Um diesen Verlust aufzufangen, können Spieler ihre Städte auf Übersee-Kontinenten in Kolonien verwandeln. Wenn diese Städte den Status einer Kolonie erhalten, gründen sie sofort ihre eigene, individuelle Zivilisation und werden Vasallen des Spielers. Sie werden von der KI gesteuert, doch der Spieler hat immer noch Zugriff auf alle Ressourcen der Kolonie. Sie können in Ihrem Überseereich eine Kolonie gründen, indem Sie die entsprechende Schaltfläche auf dem Inlandsberater-Bildschirm verwenden.[PARAGRAPH:1]Kolonien erhalten einen großen Bonus auf die Einstellung zu ihrer Elternzivilisation, und solange die Beziehungen zwischen der Elternzivilisation und der Kolonie gut sind, verbleibt die Kolonie als elterlicher Vasall. Kolonien lassen sich jedoch nicht schlecht behandeln, und wenn die Einstellung einer Kolonie zur Elternzivilisation sinkt, kann die Kolonie sich eventuell ganz lösen. Kolonien können von der Elternzivilisation nicht erneut vereinnahmt werden - sie müssen erobert werden, um sie wieder zu einem Teil Ihres Reiches zu machen. + [H1]Colonie[\H1][PARAGRAPH:2]Il mantenimento delle tue città ora tiene conto di un terzo fattore, oltre al numero di città della tua civiltà e la loro distanza dalla capitale. Questo nuovo costo di mantenimento interessa solo le città su continenti oltremare che non comprendono la tua capitale. Quando il numero di città su quel continente lontano raggiunge un certo livello, i costi di mantenimento cominceranno a prevalere sulla produzione.[PARAGRAPH:1]Per gestire tali perdite, il giocatore può trasformare le città su un continente oltremare in una Colonia. Ottenendo lo stato di Colonia, queste città creeranno immediatamente la propria distinta civiltà e saranno un vassallo del giocatore. Saranno gestite dall'IA, ma il giocatore avrà ancora accesso a tutte le risorse della colonia. Puoi scegliere di generare una Colonia con il tuo impero oltremare usando l'apposito pulsante nella schermata del Consigliere interno.[PARAGRAPH:1]Le Colonie ricevono un maggior bonus di atteggiamento verso la civiltà originaria e, fino a quando le relazioni rimangono buone tra le due, la Colonia rimarrà un vassallo. Le Colonie non si lasciano abusare e, se il loro atteggiamento verso la civiltà d'origine si inasprisce, potrebbero decidere di separarsene completamente. Le Colonie non possono più essere riassorbite dalla civiltà d'origine: se vuoi che facciano ancora parte del tuo impero dovrai conquistarle. + [H1]Colonias[\H1][PARAGRAPH:2]El mantenimiento de las ciudades ahora tiene en cuenta un tercer factor, además de la cantidad de ciudades y su lejanía con respecto a la capital. Este nuevo coste de mantenimiento solo afecta a las ciudades en continentes de ultramar, donde no tienes la capital. Cuando la cantidad de ciudades de un continente lejano alcance cierto nivel, los costes de mantenimiento empezarán a ser mayores que la producción.[PARAGRAPH:1]Para paliar estas pérdidas, el jugador puede convertir en una colonia sus ciudades de ultramar. Al concederles el estatus de colonia, éstas se separarán de su civilización originaria y se convertirán en vasallos del jugador. La IA se encargará de gestionarlas, pero el jugador seguirá teniendo acceso a todos los recursos de sus colonias. Se puede optar por crear una colonia a partir de un imperio de ultramar si se usa el botón pertinente en la pantalla del Consejero de Interior.[PARAGRAPH:1]Las colonias reciben una gran bonificación de actitud respecto a su civilización originaria y, mientras duren las relaciones entre ésta y la colonia, la colonia seguirá siendo su vasalla. Sin embargo, las colonias no aguantarán abusos. Por lo tanto, si la actitud de una colonia respecto a su civilización originaria se enrarece, romperá con ella por completo. Las colonias nunca podrán ser reabsorbidas por su civilización originaria: habrá que conquistarlas si se quiere que vuelvan a formar parte del imperio. + + + TXT_KEY_JALMODREPAIR + Repair module has completely returned. + Le module de réparation est complètement opérationnel. + Das Reparaturmodul ist wieder voll da. + Il modulo di riparazione è completamente rientrato. + El módulo de reparación está totalmente de vuelta. + + + TXT_KEY_CS_5_1_3 + Bravado and luck, buddy. Bravado and luck. + De la vantardise et de la chance ! C'est tout nous ! + Mut und Glück, Kumpel. Mut und Glück. + Coraggio e fortuna, amico. Coraggio e fortuna. + Suerte y valor, colega. Suerte y valor. + + + TXT_KEY_TECH_QUOTE_2 + [TAB]"In light of ever-increasing competition between advanced nations over resources with which to spur their struggling economies, the United States and China saw themselves locked in a dangerous dance as the 2060s passed. Both desperately sought expansion to mitigate the increasing turmoil caused by the economic collapse of the previous decade, and as a result each side's willingness to engage in negotiations diminished as conditions continued to deteriorate."[NEWLINE][NEWLINE][TAB]- Encyclopediae Galactica, History of the Earth and its Colonies + [TAB]"La concurrence accrue entre les nations les plus développées pour le contrôle des ressources s'accentua encore après 2060. Les Etats-Unis et la Chine, en particulier, développèrent des politiques très agressives dans ce sens. Ces deux nations cherchèrent par tous les moyens à se relever du chaos économique dans lequel elles avaient été plongées quelques années plus tôt, et leurs relations se détériorèrent rapidement."[NEWLINE][NEWLINE][TAB]- Encyclopédie galactique, Histoire de la Terre et de ses colonies + [TAB]"Angesichts des immer härter werdenden Wettbewerbs der fortschrittlichen Länder um die Ressourcen, die zur Steigerung der Wirtschaft benötigt werden, befanden sich die USA und China am Ende der 2060er Jahre in einer gefährlichen Situation. Beide Nationen versuchten verzweifelt zu expandieren, um die Folgen des Wirtschaftszusammenbruchs des vorhergehenden Jahrzehnts abzumildern. Die Verhandlungsbereitschaft sank auf beiden Seiten mit der Verschlechterung der Zustände."[NEWLINE][NEWLINE][TAB]- Encyclopedia Galactica, Geschichte der Erde und ihrer Kolonien + [TAB]"Alla luce della crescente competizione tra le nazioni sviluppate per accaparrarsi risorse con cui sostenere le proprie economie in difficoltà, intorno al 2060 gli Stati Uniti e la Cina si trovarono in una situazione pericolosa. Entrambi cercavano di espandersi per mitigare i tumulti causati dal collasso economico della precedente decade, e per questo la volontà di negoziare di ciascuna parte andò progressivamente diminuendo, mentre le condizioni continuavano a deteriorarsi."[NEWLINE][NEWLINE][TAB]- Enciclopedia Galattica, storia della Terra e delle sue colonie + [TAB]"En vista de la pujante competitividad entre las naciones avanzadas por los recursos con que estimular sus economías enfrentadas, los Estados Unidos y China acabaron trabados en un peligroso baile durante los años 60 del tercer milenio. Ambas naciones buscaban desesperadamente la expansión para mitigar la agitación creciente, causada por el colapso económico de la década anterior. Como consecuencia, la voluntad de ponerse a negociar disminuyó por ambas partes y la situación siguió deteriorándose."[NEWLINE][NEWLINE][TAB]- Enciclopedia Galáctica, "Historia de la Tierra y sus colonias" + + + TXT_KEY_GODS_DAWN_OF_MAN_TEXT_CHANGED + Rule Changes:[NEWLINE][COLOR_HIGHLIGHT_TEXT]Founding Religions[COLOR_REVERT][NEWLINE]Rather than being founded through technologies, Religions in gods of Old are founded by building a Shrine to a specific god in a city.[NEWLINE][COLOR_HIGHLIGHT_TEXT]Religious Victory[COLOR_REVERT][NEWLINE]For a religious victory to be obtained a player must control the last remaining Holy City. Holy Cities can be eliminated through use of Inquisitors. [NEWLINE][COLOR_HIGHLIGHT_TEXT]Inquisitors[COLOR_REVERT][NEWLINE]Inquisitors are able to eliminate all non-state religions from a city; this includes Holy Cities. [NEWLINE][COLOR_HIGHLIGHT_TEXT]Natural Disasters[COLOR_REVERT][NEWLINE]Great Prophets of some gods allow you to sacrifice the Prophet in order to call Natural Disasters upon your enemies. Prophets of Ki call Earthquakes, Prophets of Enki call Tsunamis, Prophets of Enlil cause Plagues, Prophets of Nanna bring down Meteor Strikes, and Prophets of Utu can cause Blight on an opponents land. Prophets of An offer protection from Natural Disasters and are automatically sacrificed to absorb any disasters that target their player's land. Prophets of Inanna can cause no disasters.[NEWLINE][NEWLINE]The sun rises on the year %s1_year. Since time immemorial, the %s2_civ people have lived a nomadic life. [NEWLINE][NEWLINE]After years of wandering, they are ready to settle down and found your first city. [NEWLINE]%s3_leader, your people have vested absolute power in you, trusting that you can build a Civilization to stand the test of time! + Changements de règles :[NEWLINE][COLOR_HIGHLIGHT_TEXT]Fonder des religions[COLOR_REVERT][NEWLINE]Plutôt que d'être fondées par les technologies, les religions des Dieux de l'Ancien Temps sont fondées en construisant dans une ville un autel spécifique à un dieu.[NEWLINE][COLOR_HIGHLIGHT_TEXT]Victoire religieuse[COLOR_REVERT][NEWLINE]Pour remporter une victoire religieuse, un joueur doit contrôler la dernière Ville Sainte qui subsiste. Les Villes Saintes peuvent être éliminées par les inquisiteurs. [NEWLINE][COLOR_HIGHLIGHT_TEXT]Inquisiteurs[COLOR_REVERT][NEWLINE]Les inquisiteurs ont la possibilité d'éliminer toutes les religions d'une ville qui ne sont pas des religions d'état, y compris dans les Villes Saintes. [NEWLINE][COLOR_HIGHLIGHT_TEXT]Catastrophes naturelles[COLOR_REVERT][NEWLINE]Les grands prophètes de certains dieux peuvent être sacrifiés pour invoquer des catastrophes naturelles sur vos ennemis. Les prophètes de Ki invoquent des séismes, les prophètes d'Enki invoquent des tsunamis, les prophètes d'Enlil provoquent des épidémies, les prophètes de Nanna font pleuvoir des météorites et les prophètes d'Utu peuvent provoquer la rouille sur les territoires adverses. Les prophètes d'An offrent une protection contre les catastrophes naturelles et sont automatiquement sacrifiés pour contrer toute catastrophe qui frappe les terres du joueur. Les prophètes d'Inanna ne peuvent pas invoquer de catastrophes.[NEWLINE][NEWLINE]Le soleil se lève sur l'an %s1_year. Depuis des temps immémoriaux, le peuple %s2_civ menait une vie nomade. [NEWLINE][NEWLINE]Après des années d'errance, il est prêt à se sédentariser et à fonder votre première ville. [NEWLINE]%s3_leader, votre peuple vous a investi du pouvoir absolu et vous fait confiance pour bâtir une civilisation qui résistera au cours du temps ! + Regeländerungen:[NEWLINE][COLOR_HIGHLIGHT_TEXT]Religion gründen[COLOR_REVERT][NEWLINE]Statt durch Technologien gegründet zu werden, werden die Religionen in Gods of Old gegründet, indem in einer Stadt ein Schrein einer bestimmten Gottheit errichtet wird.[NEWLINE][COLOR_HIGHLIGHT_TEXT]Religiöser Sieg[COLOR_REVERT][NEWLINE]Um den Religiösen Sieg zu erringen, muss ein Spieler die letzte verbliebene Heilige Stadt kontrollieren. Heilige Städte können mit der Hilfe von Inquisitoren vernichtet werden.[NEWLINE][COLOR_HIGHLIGHT_TEXT]Inquisitoren[COLOR_REVERT][NEWLINE]Inquisitoren können in einer Stadt alle Religionen eliminieren, die nicht Staatsreligion sind; dies gilt auch für Heilige Städte.[NEWLINE][COLOR_HIGHLIGHT_TEXT]Naturkatastrophen[COLOR_REVERT][NEWLINE]Große Propheten einiger Götter ermöglichen es, den Propheten zu opfern, um Naturkatastrophen über die Feinde zu bringen. Ki-Propheten rufen Erdbeben hervor, Enki-Propheten rufen Tsunamis hervor, Enlil-Propheten rufen die Pest hervor, Nanna-Propheten verursachen Meteoritenschläge und Utu-Propheten verursachen eine Dürre auf gegnerischem Land. An-Propheten bieten Schutz vor Naturkatastrophen und werden automatisch geopfert, um Naturkatastrophen abzuwenden, die gegen das Land ihres Spielers gerichtet sind. Inanna-Propheten können keine Katastrophen verursachen.[NEWLINE][NEWLINE]Die Sonne erhellt das Jahr %s1_year. Das %s2:3_civ Volk führt seit uralter Zeit ein Nomadenleben. [NEWLINE][NEWLINE]Doch nun, nach so vielen Jahren des Umherziehens, sind die Menschen bereit, sich niederzulassen und Eure erste Stadt zu gründen. [NEWLINE]%s3_leader, Euer Volk hat Euch absolute Macht verliehen und vertraut darauf, dass Ihr eine Zivilisation errichtet, welche die Zeit überdauern wird! + Cambiamenti nelle regole:[NEWLINE][COLOR_HIGHLIGHT_TEXT]Fondare religioni[COLOR_REVERT][NEWLINE]In Antiche divinità le religioni, invece di essere fondate con le tecnologie, si fondano costruendo in una città un santuario dedicato a una specifica divinità.[NEWLINE][COLOR_HIGHLIGHT_TEXT]Vittoria religiosa[COLOR_REVERT][NEWLINE]Per ottenere una vittoria religiosa è necessario controllare l'ultima Città Santa che rimane. Le Città Sante possono essere eliminate usando gli inquisitori. [NEWLINE][COLOR_HIGHLIGHT_TEXT]Inquisitori[COLOR_REVERT][NEWLINE]Gli inquisitori sono in grado di eliminare da una città tutte le religioni non di stato, anche nelle Città Sante. [NEWLINE][COLOR_HIGHLIGHT_TEXT]Disastri naturali[COLOR_REVERT][NEWLINE]I Grandi Profeti di alcune divinità permettono di scatenare disastri naturali sui nemici, a patto di sacrificare il profeta stesso. I profeti di Ki scatenano terremoti, quelli di Enki tsunami, quelli di Enlil pestilenze, quelli di Nanna fanno cadere meteoriti e i profeti di Utu possono distruggere le terre di un avversario. I profeti di An offrono protezione dai disastri naturali e vengono sacrificati automaticamente per assorbire i disastri che colpiscono i loro territori. I profeti di Inanna non possono causare disastri.[NEWLINE][NEWLINE]Il sole sorge nell'anno %s1_year. Da tempi immemori, la popolazione %s2_civ ha condotto una vita nomade. [NEWLINE][NEWLINE]Dopo anni di vagabondaggi, sono infine pronti a stabilirsi e a fondare la tua prima città. [NEWLINE]%s3_leader, il tuo popolo ti ha conferito potere assoluto, credendo che tu possa sviluppare una civiltà in grado di resistere alle prove del tempo! + Cambios de reglas:[NEWLINE][COLOR_HIGHLIGHT_TEXT]Fundación de religiones[COLOR_REVERT][NEWLINE]En lugar de fundarse gracias a las tecnologías, las religiones en "Gods of Old" se fundan al construir un santuario a un dios específico en una ciudad.[NEWLINE][COLOR_HIGHLIGHT_TEXT]Victoria religiosa[COLOR_REVERT][NEWLINE]Para obtener una victoria religiosa, el jugador debe controlar la última ciudad santa restante. Las ciudades santas se pueden eliminar con los inquisidores. [NEWLINE][COLOR_HIGHLIGHT_TEXT]Inquisidores[COLOR_REVERT][NEWLINE]Los inquisidores pueden eliminar todas las religiones no oficiales de una ciudad, incluyendo las ciudades santas. [NEWLINE][COLOR_HIGHLIGHT_TEXT]Desastres naturales[COLOR_REVERT][NEWLINE]Los grandes profetas de algunos dioses pueden sacrificarse para provocar desastres naturales a tus enemigos. Los profetas de Ki convocan terremotos, los de Enki convocan tsunamis, los de Enlil causan pestes, los de Nanna atraen meteoritos y los de Utu pueden provocar accidentes sobre las tierras de los rivales. Los profetas de An ofrecen protección frente a los desastres naturales y se sacrifican automáticamente para absorber los desastres que afecten a la tierra de su jugador. Los profetas de Inanna no pueden provocar desastres.[NEWLINE][NEWLINE]El sol se alza en el año %s1_year. Desde tiempos inmemoriales, los %s2:3_civ han llevado una vida nómada. [NEWLINE][NEWLINE]Tras años de deambular, están listos para asentarse y fundar vuestra primera ciudad. [NEWLINE]%s3_leader, vuestro pueblo os ha conferido poder absoluto, confiando en que podáis desarrollar una civilización que supere los retos del tiempo. + + + TXT_KEY_OPTIONS_NO_SOUND + No Sound + Muet + Kein Ton + Muto + Sin sonido + + + TXT_KEY_OPTIONS_EFFECTSVOLUME + Sound Effects + Vol. effets sonores + Soundeffekte + Volume effetti sonori + Volumen de los efectos de sonido + + + TXT_KEY_HALL_OF_FAME_SCREEN_TITLE + Hall of Fame + Panthéon + Ruhmeshalle + Hall of Fame + Salón de la Fama + + + TXT_KEY_POPUP_REGENERATE_MAP + Regenerate Map + Régénérer carte + Karte neu laden + Rigenera mappa + Regenerar mapa + + + TXT_KEY_TOPCIVS_RANK1 + Glorious + un chef glorieux + Glorreiche + Glorioso + Glorios + + + TXT_KEY_TOPCIVS_RANK2 + Great + un grand chef + Großartige + Grande + Grandios + + + TXT_KEY_TOPCIVS_RANK3 + Fine + un chef raffiné + Beachtliche + Eccellente + Adecuad + + + TXT_KEY_TOPCIVS_RANK4 + Mediocre + un chef médiocre + Mittelmäßige + Mediocre + Deslucid + + + TXT_KEY_TOPCIVS_RANK5 + Puny + un chef faible + Armselige + Debole + Debiluch + + + TXT_KEY_TOPCIVS_RANK6 + Pathetic + un chef pitoyable + Jämmerliche + Patetico + Patétic + + + TXT_KEY_TOPCIVS_RANK7 + Hopeless + un chef affligeant + Hoffnungslose + Disperato + Deshauciad + + + TXT_KEY_TOPCIVS_RANK8 + Forgotten + un chef oublié + Vergessene + Dimenticato + Olvidad + + + TXT_KEY_UNIT_AZTEC_JAGUAR_STRATEGY + This powerful melee combat unit (the Aztec replacement for the [COLOR_UNIT_TEXT]Swordsman[COLOR_REVERT]) is special because it requires no special resource and gets a bonus in [COLOR_UNIT_TEXT]Jungles[COLOR_REVERT]. + Puissante unité de combat rapproché (l'unité aztèque qui vient remplacer le [COLOR_UNIT_TEXT]spadassin[COLOR_REVERT]) dont la production ne coûte aucune ressource. Elle bénéficie d'un fort bonus dans la [COLOR_UNIT_TEXT]jungle[COLOR_REVERT]. + Diese effektive Nahkampfeinheit (die aztekische Variante des [COLOR_UNIT_TEXT]Schwertkämpfers[COLOR_REVERT]) benötigt keine besonderen Ressourcen und hat im [COLOR_UNIT_TEXT]Dschungel[COLOR_REVERT] einen Bonus. + Questa potente unità da combattimento corpo a corpo (l'equivalente Azteco dello [COLOR_UNIT_TEXT]spadaccino[COLOR_REVERT]) è speciale, poiché non richiede risorse e ottiene un bonus nella [COLOR_UNIT_TEXT]giungla[COLOR_REVERT]. + Esta poderosa unidad de cuerpo a cuerpo (que sustituye al [COLOR_UNIT_TEXT]Soldado con espada[COLOR_REVERT] en la civilización azteca) es especial porque no requiere un recurso y obtiene una bonificación en las [COLOR_UNIT_TEXT]Selvas[COLOR_REVERT]. + + + TXT_KEY_CIVIC_BUILDING_YIELD_CHANGE + [ICON_BULLET]%D1_Change%F2_Icon from[SPACE] + [ICON_BULLET]%D1_Change%F2_Icon :[SPACE] + [ICON_BULLET]%D1_Change%F2_Icon das Gebäude[SPACE] + [ICON_BULLET]%D1_Change%F2_Icon da[SPACE] + [ICON_BULLET]%D1_Change %F2_Icon por[SPACE] + + + TXT_KEY_CIVIC_BUILDING_YIELD_MODIFIER + [ICON_BULLET]%D1_Mod%%F2_Icon from[SPACE] + [ICON_BULLET]%D1_Mod%%F2_Icon :[SPACE] + [ICON_BULLET]%D1_Mod%%F2_Icon das Gebäude[SPACE] + [ICON_BULLET]%D1_Change%%F2_Icon da[SPACE] + [ICON_BULLET]%D1_Change%%F2_Icon por[SPACE] + + + TXT_KEY_CIVIC_BUILDING_COMMERCE_CHANGE + [ICON_BULLET]%D1_Change%F2_Icon from[SPACE] + [ICON_BULLET]%D1_Change%F2_Icon :[SPACE] + [ICON_BULLET]%D1_Change%F2_Icon das Gebäude[SPACE] + [ICON_BULLET]%D1_Change%F2_Icon da[SPACE] + [ICON_BULLET]%D1_Change%F2_Icon por[SPACE] + + + TXT_KEY_CIVIC_BUILDING_COMMERCE_MODIFIER + [ICON_BULLET]%D1_Change%%%F2_Icon from[SPACE] + [ICON_BULLET]%D1_Change%%%F2_Icon :[SPACE] + [ICON_BULLET]%D1_Change%%%F2_Icon das Gebäude[SPACE] + [ICON_BULLET]%D1_Change%%%F2_Icon da[SPACE] + [ICON_BULLET]%D1_Change%%%F2_Icon por[SPACE] + + + TXT_KEY_CIVIC_BUILDING_FREE_EXPERIENCE + [ICON_BULLET]New Units Receive %D1_Change Experience Points from [COLOR_BUILDING_TEXT][LINK=literal]%s2_Building[\LINK][COLOR_REVERT] + [ICON_BULLET]Les nouvelles unités bénéficient de %D1_Change EXP : [COLOR_BUILDING_TEXT][LINK=literal]%s2_Building[\LINK][COLOR_REVERT] + [ICON_BULLET]Neue Einheiten erhalten %D1_Change Erfahrungspunkte das Gebäude [COLOR_BUILDING_TEXT][LINK=literal]%s2_Building[\LINK][COLOR_REVERT] + [ICON_BULLET]Le nuove unità ricevono %D1_Change punti esperienza da [COLOR_BUILDING_TEXT][LINK=literal]%s2_Building[\LINK][COLOR_REVERT] + [ICON_BULLET]Las nuevas unidades reciben %D1_Change [NUM1:punto de experiencia:puntos de experiencia] por [COLOR_BUILDING_TEXT][LINK=literal]%s2_Building[\LINK][COLOR_REVERT] + + + TXT_KEY_CIVIC_BUILDING_MILITARY_PRODUCTION + [ICON_BULLET]%D1_Mod%% Military Unit Production from [COLOR_BUILDING_TEXT][LINK=literal]%s2_Building[\LINK][COLOR_REVERT] + [ICON_BULLET]%D1_Mod%% de production d'unités militaires : [COLOR_BUILDING_TEXT][LINK=literal]%s2_Building[\LINK][COLOR_REVERT] + [ICON_BULLET]%D1_Mod%% Produktion von Militäreinheiten das Gebäude [COLOR_BUILDING_TEXT][LINK=literal]%s2_Building[\LINK][COLOR_REVERT] + [ICON_BULLET]%D1_Mod%% di produzione nelle unità militari da [COLOR_BUILDING_TEXT][LINK=literal]%s2_Building[\LINK][COLOR_REVERT] + [ICON_BULLET]%D1_Mod%% a la producción de unidades militares por [COLOR_BUILDING_TEXT][LINK=literal]%s2_Building[\LINK][COLOR_REVERT] + + + TXT_KEY_CIVIC_BUILDING_FREE_SPECIALIST + [ICON_BULLET]%D1_Change [COLOR_HIGHLIGHT_TEXT][LINK=literal]%s2_SpclstName[\LINK][COLOR_REVERT] from[SPACE] + [ICON_BULLET]%D1_Change [COLOR_HIGHLIGHT_TEXT][LINK=literal]%s2_SpclstName[\LINK][COLOR_REVERT] :[SPACE] + [ICON_BULLET]%D1_Change [COLOR_HIGHLIGHT_TEXT][LINK=literal]%s2_SpclstName[\LINK][COLOR_REVERT] das Gebäude[SPACE] + [ICON_BULLET]%D1_Change [COLOR_HIGHLIGHT_TEXT][LINK=literal]%s2_SpclstName[\LINK][COLOR_REVERT] da[SPACE] + [ICON_BULLET]%D1_Change [COLOR_HIGHLIGHT_TEXT][LINK=literal]%s2_SpclstName[\LINK][COLOR_REVERT] por[SPACE] + + + TXT_KEY_BUILDING_CIVIC_FREE_XP + [ICON_BULLET]%D1_Change Experience Points with[SPACE] + [ICON_BULLET]%D1_Change EXP avec[SPACE] + [ICON_BULLET]%D1_Change Erfahrungspunkte mit[SPACE] + [ICON_BULLET]%D1_Change punti esperienza con[SPACE] + [ICON_BULLET]%D1_Change [NUM1:punto de experiencia:puntos de experiencia] con[SPACE] + + + TXT_KEY_BUILDING_CIVIC_FREE_XP_LONG + [ICON_BULLET]New Units Receive %D1_Change Experience Points with[SPACE] + [ICON_BULLET]Les nouvelles unités bénéficient de %D1_Change EXP avec[SPACE] + [ICON_BULLET]Neue Einheiten erhalten %D1_Change Erfahrungspunkte mit[SPACE] + [ICON_BULLET]Le nuove unità ricevono %D1_Change punti esperienza con[SPACE] + [ICON_BULLET]Las nuevas unidades reciben %D1_Change [NUM1:punto de experiencia:puntos de experiencia] con[SPACE] + + + TXT_KEY_BUILDING_CIVIC_FREE_SPECIALIST + [ICON_BULLET]%D1_Change Free [COLOR_HIGHLIGHT_TEXT][LINK=literal]%s2_SpclstName[\LINK][COLOR_REVERT] with[SPACE] + [ICON_BULLET]%D1_Change Donne un [COLOR_HIGHLIGHT_TEXT][LINK=literal]%s2_SpclstName[\LINK][COLOR_REVERT] gratuit avec[SPACE] + [ICON_BULLET]%D1_Change freien Spezialisten [COLOR_HIGHLIGHT_TEXT][LINK=literal]%s2_SpclstName[\LINK][COLOR_REVERT] mit[SPACE] + [ICON_BULLET]%D1_Change [COLOR_HIGHLIGHT_TEXT][LINK=literal]%s2_SpclstName[\LINK][COLOR_REVERT] gratis con[SPACE] + [ICON_BULLET]%D1_Change [COLOR_HIGHLIGHT_TEXT][LINK=literal]%s2_SpclstName[\LINK][COLOR_REVERT] gratis con[SPACE] + + + TXT_KEY_BUILDING_CIVIC_WITH + [SPACE]with[SPACE] + [SPACE]avec[SPACE] + [SPACE]mit[SPACE] + [SPACE]con[SPACE] + [SPACE]con[SPACE] + + + TXT_KEY_BUILDING_CIVIC_MILITARY_PRODUCTION + [ICON_BULLET]%D1_Mod%% Military Unit Production with[SPACE] + [ICON_BULLET]%D1_Mod%% de production d'unités militaires avec[SPACE] + [ICON_BULLET]%D1_Mod%% Produktion von Militäreinheiten mit[SPACE] + [ICON_BULLET]%D1_Mod%% di produzione nelle unità militari con[SPACE] + [ICON_BULLET]%D1_Mod%% a la producción de unidades militares con[SPACE] + + + TXT_KEY_MISC_TRAITS_MAINT + %s1_MaintNum [ICON_GOLD]: Leader traits + %s1_MaintNum [ICON_GOLD] : traits de caractère + %s1_MaintNum [ICON_GOLD]: Eigenschaften Staatsoberhäupterns + %s1_MaintNum [ICON_GOLD]: caratteristiche dei leader + %s1_MaintNum [ICON_GOLD]: rasgos de los líderes + + + TXT_KEY_TRAIT_CITY_UPKEEP_MODIFIER + [NEWLINE][SPACE][SPACE][ICON_BULLET]%D1%% City Maintenance + [NEWLINE][SPACE][SPACE][ICON_BULLET]%D1%% Entretien ville + [NEWLINE][SPACE][SPACE][ICON_BULLET]%D1%% Stadtunterhalt + [NEWLINE][SPACE][SPACE][ICON_BULLET]%D1%% Mantenimento città + [NEWLINE][SPACE][SPACE][ICON_BULLET]%D1%% Mantenimiento de las ciudades + + diff --git a/Mod/RB Mod/Assets/CvGameCoreDLL.dll b/Mod/RB Mod/Assets/CvGameCoreDLL.dll index 6780438..22fa09e 100644 Binary files a/Mod/RB Mod/Assets/CvGameCoreDLL.dll and b/Mod/RB Mod/Assets/CvGameCoreDLL.dll differ diff --git a/Mod/RB Mod/Assets/Python/CvGameInterface.py b/Mod/RB Mod/Assets/Python/CvGameInterface.py new file mode 100644 index 0000000..5b65177 --- /dev/null +++ b/Mod/RB Mod/Assets/Python/CvGameInterface.py @@ -0,0 +1,510 @@ +## Sid Meier's Civilization 4 +## Copyright Firaxis Games 2005 +## +## ##### WARNING - MODIFYING THE FUNCTION NAMES OF THIS FILE IS PROHIBITED ##### +## +## The app specifically calls the functions as they are named. Use this file to pass +## args to another file that contains your modifications +## +## MODDERS - If you create a GameUtils file, update the CvGameInterfaceFile reference to point to your new file + +# +import CvUtil +import CvGameUtils +import CvGameInterfaceFile +import CvEventInterface +from CvPythonExtensions import * + +# novice: +# Added imports for getGameStateString: +import string +import time +from PyHelpers import PyGame, PyPlayer + +# globals +gc = CyGlobalContext() +normalGameUtils = CvGameInterfaceFile.GameUtils + +# novice: Added entry point getGameStateString to be called from the C++ code. +def getGameStateString(argslist): + try: + #print("Dumping game state...") + religionCount = 7 + buildingCount = 159 + promotionTypeCount = 54 + specialistTypeCount = 14 + technologyCount = gc.getNumTechInfos() + cyMap = CyMap() + cyGame = CyGame() + pyGame = PyGame() + #testvar = 123/0 + plots = [] + players = [] + #print(".Dumping player state...") + for p in pyGame.getCivPlayerList(): + team = p.getTeam() + pp = p.getPlayer() + contacts = [] + #print("..Dumping player " + str(p.getID()) + " contacts...") + for op in range(gc.getMAX_CIV_PLAYERS()): + if pp.canContact(op): + contacts.append(op) + #print("..Dumping player " + str(p.getID()) + " techs...") + techProgress = [] + for t in range(technologyCount-1): + techProgress.append(team.getResearchProgress(t)) + cities = [] + #print("..Dumping player " + str(p.getID()) + " cities...") + for c in p.getCityList(): + cc = c.GetCy() + buildings = [] + buildQueue = [] + religions = [] + holyCities = [] + freeSpecialists = [] + specialists = [] + for s in range(specialistTypeCount-1): + for i in range(cc.getAddedFreeSpecialistCount(s)): + freeSpecialists.append(s) + for i in range(cc.getSpecialistCount(s)): + specialists.append(s) + for r in range(religionCount-1): + if(cc.isHasReligion(r)): + religions.append(r) + if(cc.isHolyCityByType(r)): + holyCities.append(r) + for b in range(buildingCount-1): + if cc.getNumBuilding(b) > 0: + buildings.append(b) + for q in range(cc.getOrderQueueLength()): + order = cc.getOrderFromQueue(q) + buildQueue.append({"save": order.bSave, "type": int(order.eOrderType), "data1": order.iData1, "data2": order.iData2}) + cities.append({ + "ID": c.getID(), + "x": c.getX(), + "y": c.getY(), + #"index": c.getIndex(), + "name": c.getName().replace("'", ""), + "owner": c.getOwner(), + "isBarbarian" : c.isBarbarian(), + "size" : c.getPopulation(), + "maintenance" : { "colony": cc.calculateColonyMaintenanceTimes100(), "distance": cc.calculateDistanceMaintenanceTimes100(), "numCities": cc.calculateNumCitiesMaintenanceTimes100(), "corps" : cc.calculateCorporationMaintenanceTimes100() }, + "food" : { "fpt": cc.getYieldRate(0), "food" : cc.getFood(), "difference" : cc.foodDifference(False), "foodKept" : cc.getFoodKept(), "foodTurnsLeft" : cc.getFoodTurnsLeft() }, + "happy" : { "espionageCounter": cc.getEspionageHappinessCounter(), "extra": cc.getExtraHappiness(), "totalHappy" : cc.happyLevel(), "angryPopulation" : cc.angryPopulation(0) }, #"fromBuildings" : cc.getBuildingHappiness(), "fromReligionGood": cc.getReligionGoodHappiness(), "fromReligionBad": cc.getReligionBadHappiness() }, # "totalGood": cc.calculateTotalCityHappiness(), "totalBad": cc.calculateTotalCityUnhappiness(), + "health" : { "espionageCounter": cc.getEspionageHealthCounter(), "goodHealth": cc.goodHealth(), "badHealth" : cc.badHealth(false), "fromResourcesGood" : cc.getBonusGoodHealth(), "fromResourcesBad" : cc.getBonusBadHealth(), "extra" : cc.getExtraHealth(), "fromBuildingsGood" : cc.getBuildingGoodHealth(), "fromBuildingsBad" : cc.getBuildingBadHealth()}, # "totalGood": cc.calculateTotalCityHealthiness (), "totalBad": cc.calculateTotalCityUnhealthiness(), + "production" : { "hpt": cc.getYieldRate(1), "isFood" : cc.isFoodProduction(), "overflow" : cc.getOverflowProduction(), "hammersInBox" : cc.getProduction(), "hammersNeeded" : cc.getProductionNeeded(), "name" : cc.getProductionName(), "process": cc.getProductionProcess(), "project": cc.getProductionProject(), "building": cc.getProductionBuilding(), "unit" : cc.getProductionUnit(), "turnsLeft": cc.getProductionTurnsLeft()}, + "commerce" : { "cpt" : cc.getYieldRate(2) }, + "specialists": specialists, + "freeSpecialists": freeSpecialists, + "buildings": buildings, + "buildQueue": buildQueue, + "religions": religions, + "holyCities": holyCities + }) + #print("..Dumping player " + str(p.getID()) + " player info...") + currentResearch = pp.getCurrentResearch() + currentTechTurnsLeft = 0 + if currentResearch >= 0: + currentTechTurnsLeft = pp.getResearchTurnsLeft(currentResearch, True) + players.append({ + "isAlive" : p.isAlive(), + "ID" : p.getID(), + "name" : p.getName(), + "handicap" : int(pp.getHandicapType()), + "color" : pp.getPlayerColor(), + "team" : p.getTeamID(), + "contacts" : contacts, + "civics" : p.getCurrentCivicList(), + "gold" : p.getGold(), + "maintenanceCosts" : p.getTotalMaintenance(), + "unitCosts": p.calculateUnitCost(), + "unitSupply" : p.calculateUnitSupply(), + "goldCommerceRate" : p.getGoldCommerceRate(), + "researchCommerceRate" : p.getResearchCommerceRate(), + "cultureCommerceRate" : p.getCultureCommerceRate(), + "espionageCommerceRate" : pp.getCommerceRate(CommerceTypes.COMMERCE_ESPIONAGE), + "beakersPerTurn" : p.calculateResearchRate(), + "goldPerTurn" : p.getGoldPerTurn(), + "techs" : p.getResearchedTechList(), + "techProgress" : techProgress, + "currentTechName" : p.getCurrentTechName(), + "currentTech" : currentResearch, + "overflowResearch" : pp.getOverflowResearch(), + "currentTechTurnsLeft" : currentTechTurnsLeft, + "civType" : pp.getCivilizationType(), + "civDescription" : p.getCivDescription().replace("'", ""), + "civName" : p.getCivilizationName().replace("'", ""), + "civShortDescription" : p.getCivilizationShortDescription().replace("'", ""), + "civAdjective": p.getCivilizationAdjective().replace("'", ""), + "leaderName" : p.getLeaderName().replace("'", ""), + "leaderType": p.getLeaderType(), + "sliders": { "gold": pp.getCommercePercent(0), "research": pp.getCommercePercent(1), "culture": pp.getCommercePercent(2), "espionage": pp.getCommercePercent(3) }, + "cities": cities + }) + #print(".Dumping map state...") + for x in range(cyMap.getGridWidth()): + for y in range(cyMap.getGridHeight()): + plot = cyMap.plot(x, y) + wc = plot.getWorkingCity() + wcid = -1 + if not wc is None: + wcid = wc.getID() + visible = [] + revealed = [] + culture = [] + units = [] + for u in range(plot.getNumUnits()): + unit = plot.getUnit(u) + transportUnitID = -1 + if(not unit.getTransportUnit() is None): + transportUnitID = unit.getTransportUnit().getID() + promotions = [] + for pr in range(promotionTypeCount-1): + if unit.isHasPromotion(pr): + promotions.append(pr) + units.append({ + "cargo": unit.getCargo(), + "damage": unit.getDamage(), + "buildType" : int(unit.getBuildType()), + "xp": unit.getExperience(), + "level": unit.getLevel(), + "name" : unit.getName(), + "moves" : unit.getMoves(), + "owner" : unit.getOwner(), + "ID" : unit.getID(), + "transportUnit" : transportUnitID, + "unitType" : unit.getUnitType(), + "fortifyTurns" : unit.getFortifyTurns(), + "promotions": promotions + }) + for p in range(len(players)): + culture.append(plot.getCulture(p)) + for t in range(cyGame.countCivTeamsEverAlive()): + revealed.append(plot.isRevealed(t, False)) + visible.append(plot.isVisible(t, False)) + plots.append({"x": x, "y": y, + "wcid": wcid, + "worked": plot.isBeingWorked(), + "bonus": plot.getBonusType(plot.getTeam()), + "terrain": plot.getTerrainType(), + "improvement": plot.getImprovementType(), + "feature": { "type" : plot.getFeatureType(), "variety": plot.getFeatureVariety() }, + "river" : { "id" : plot.getRiverID(), "isNOfRiver" : plot.isNOfRiver(), "isWOfRiver": plot.isWOfRiver(), "isRiverSide" : plot.isRiverSide(), "nsDir" : int(plot.getRiverNSDirection()), "weDir" : int(plot.getRiverWEDirection()) }, + "isGoody": plot.isGoody(), + "isImpassable" : plot.isImpassable(), + "isFreshWater" : plot.isFreshWater(), + "isIrrigated" : plot.isIrrigated(), + "routeType" : plot.getRouteType(), + "plotType" : int(plot.getPlotType()), + "visible": visible, + "revealed": revealed, + "culture" : culture, + "owner" : plot.calculateCulturalOwner(), + "units" : units + }) + #print(".Dumping game settings state...") + jsondata = { + "game": { + "name": cyGame.getName().replace("'", ""), + "turn": cyGame.getGameTurn(), + "year": cyGame.getGameTurnYear(), + "isCircumnavigated" : cyGame.isCircumnavigated(), + "speed" : int(cyGame.getGameSpeedType()), + "startEra" : int(cyGame.getStartEra()), + "playerCount" : cyGame.countCivPlayersEverAlive(), + "isPbem" : cyGame.isPbem(), + "isPitboss" : cyGame.isPitboss(), + "isPitbossHost" : cyGame.isPitbossHost() + }, + "players" : players, + "map": { + "isWrapX" : cyMap.isWrapX(), + "isWrapY" : cyMap.isWrapY(), + "width" : cyMap.getGridWidth(), + "height" : cyMap.getGridHeight(), + "worldSize" : int(cyMap.getWorldSize()), + "plots": plots + } + } + #print(".Creating json file...") + #print(".Using file name " + filename + "...") + jsonstring = str(jsondata) + jsonstring = jsonstring.replace(": u'", ": \"") + jsonstring = jsonstring.replace("'", "\"") + jsonstring = jsonstring.replace("False", "false") + jsonstring = jsonstring.replace("True", "true") + jsonstring = jsonstring.replace("}", "}\n") + return jsonstring + except Exception, err: + return "{ \"error\": \"" + str(err) + "\" }" + +def gameUtils(): + ' replace normalGameUtils with your mod version' + return normalGameUtils + +def isVictoryTest(): + #CvUtil.pyPrint( "CvGameInterface.isVictoryTest" ) + return gameUtils().isVictoryTest() + +def isVictory(argsList): + return gameUtils().isVictory(argsList) + +def isPlayerResearch(argsList): + #CvUtil.pyPrint( "CvGameInterface.isPlayerResearch" ) + return gameUtils().isPlayerResearch(argsList) + +def getExtraCost(argsList): + #CvUtil.pyPrint( "CvGameInterface.getExtraCost" ) + return gameUtils().getExtraCost(argsList) + +def createBarbarianCities(): + #CvUtil.pyPrint( "CvGameInterface.createBarbarianCities" ) + return gameUtils().createBarbarianCities() + +def createBarbarianUnits(): + #CvUtil.pyPrint( "CvGameInterface.createBarbarianUnits" ) + return gameUtils().createBarbarianUnits() + +def skipResearchPopup(argsList): + #CvUtil.pyPrint( "CvGameInterface.skipResearchPopup" ) + return gameUtils().skipResearchPopup(argsList) + +def showTechChooserButton(argsList): + #CvUtil.pyPrint( "CvGameInterface.showTechChooserButton" ) + return gameUtils().showTechChooserButton(argsList) + +def getFirstRecommendedTech(argsList): + #CvUtil.pyPrint( "CvGameInterface.getFirstRecommendedTech" ) + return gameUtils().getFirstRecommendedTech(argsList) + +def getSecondRecommendedTech(argsList): + #CvUtil.pyPrint( "CvGameInterface.getSecondRecommendedTech" ) + return gameUtils().getSecondRecommendedTech(argsList) + +def skipProductionPopup(argsList): + #CvUtil.pyPrint( "CvGameInterface.skipProductionPopup" ) + return gameUtils().skipProductionPopup(argsList) + +def canRazeCity(argsList): + #CvUtil.pyPrint( "CvGameInterface.canRazeCity" ) + return gameUtils().canRazeCity(argsList) + +def canDeclareWar(argsList): + #CvUtil.pyPrint( "CvGameInterface.canRazeCity" ) + return gameUtils().canDeclareWar(argsList) + +def showExamineCityButton(argsList): + #CvUtil.pyPrint( "CvGameInterface.showExamineCityButton" ) + return gameUtils().showExamineCityButton(argsList) + +def getRecommendedUnit(argsList): + #CvUtil.pyPrint( "CvGameInterface.getRecommendedUnit" ) + return gameUtils().getRecommendedUnit(argsList) + +def getRecommendedBuilding(argsList): + #CvUtil.pyPrint( "CvGameInterface.getRecommendedBuilding" ) + return gameUtils().getRecommendedBuilding(argsList) + +def updateColoredPlots(): + #CvUtil.pyPrint( "CvGameInterface.updateColoredPlots" ) + return gameUtils().updateColoredPlots() + +def isActionRecommended(argsList): + #CvUtil.pyPrint( "CvGameInterface.isActionRecommended" ) + return gameUtils().isActionRecommended(argsList) + +def unitCannotMoveInto(argsList): + return gameUtils().unitCannotMoveInto(argsList) + +def cannotHandleAction(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotHandleAction" ) + return gameUtils().cannotHandleAction(argsList) + +def canBuild(argsList): + #CvUtil.pyPrint( "CvGameInterface.canBuild" ) + return gameUtils().canBuild(argsList) + +def cannotFoundCity(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotHandleAction" ) + return gameUtils().cannotFoundCity(argsList) + +def cannotSelectionListMove(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotSelectionListMove" ) + return gameUtils().cannotSelectionListMove(argsList) + +def cannotSelectionListGameNetMessage(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotSelectionListGameNetMessage" ) + return gameUtils().cannotSelectionListGameNetMessage(argsList) + +def cannotDoControl(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotDoControl" ) + return gameUtils().cannotDoControl(argsList) + +def canResearch(argsList): + #CvUtil.pyPrint( "CvGameInterface.canResearch" ) + return gameUtils().canResearch(argsList) + +def cannotResearch(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotResearch" ) + return gameUtils().cannotResearch(argsList) + +def canDoCivic(argsList): + #CvUtil.pyPrint( "CvGameInterface.canDoCivic" ) + return gameUtils().canDoCivic(argsList) + +def cannotDoCivic(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotDoCivic" ) + return gameUtils().cannotDoCivic(argsList) + +def canTrain(argsList): + #CvUtil.pyPrint( "CvGameInterface.canTrain" ) + return gameUtils().canTrain(argsList) + +def cannotTrain(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotTrain" ) + return gameUtils().cannotTrain(argsList) + +def canConstruct(argsList): + #CvUtil.pyPrint( "CvGameInterface.canConstruct" ) + return gameUtils().canConstruct(argsList) + +def cannotConstruct(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotConstruct" ) + return gameUtils().cannotConstruct(argsList) + +def canCreate(argsList): + #CvUtil.pyPrint( "CvGameInterface.canCreate" ) + return gameUtils().canCreate(argsList) + +def cannotCreate(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotCreate" ) + return gameUtils().cannotCreate(argsList) + +def canMaintain(argsList): + #CvUtil.pyPrint( "CvGameInterface.canMaintain" ) + return gameUtils().canMaintain(argsList) + +def cannotMaintain(argsList): + #CvUtil.pyPrint( "CvGameInterface.cannotMaintain" ) + return gameUtils().cannotMaintain(argsList) + +def AI_chooseTech(argsList): + 'AI chooses what to research' + #CvUtil.pyPrint( "CvGameInterface.AI_chooseTech" ) + return gameUtils().AI_chooseTech(argsList) + +def AI_chooseProduction(argsList): + 'AI chooses city production' + #CvUtil.pyPrint( "CvGameInterface.AI_chooseProduction" ) + return gameUtils().AI_chooseProduction(argsList) + +def AI_unitUpdate(argsList): + 'AI moves units - return 0 to let AI handle it, return 1 to say that the move is handled in python ' + #CvUtil.pyPrint( "CvGameInterface.AI_unitUpdate" ) + return gameUtils().AI_unitUpdate(argsList) + +def AI_doWar(argsList): + 'AI decides whether to make war or peace - return 0 to let AI handle it, return 1 to say that the move is handled in python ' + #CvUtil.pyPrint( "CvGameInterface.AI_doWar" ) + return gameUtils().AI_doWar(argsList) + +def AI_doDiplo(argsList): + 'AI decides does diplomacy for the turn - return 0 to let AI handle it, return 1 to say that the move is handled in python ' + #CvUtil.pyPrint( "CvGameInterface.AI_doDiplo" ) + return gameUtils().AI_doDiplo(argsList) + +def calculateScore(argsList): + return gameUtils().calculateScore(argsList) + +def doHolyCity(): + #CvUtil.pyPrint( "CvGameInterface.doHolyCity" ) + return gameUtils().doHolyCity() + +def doHolyCityTech(argsList): + #CvUtil.pyPrint( "CvGameInterface.doHolyCityTech" ) + return gameUtils().doHolyCityTech(argsList) + +def doGold(argsList): + #CvUtil.pyPrint( "CvGameInterface.doGold" ) + return gameUtils().doGold(argsList) + +def doResearch(argsList): + #CvUtil.pyPrint( "CvGameInterface.doResearch" ) + return gameUtils().doResearch(argsList) + +def doGoody(argsList): + #CvUtil.pyPrint( "CvGameInterface.doGoody" ) + return gameUtils().doGoody(argsList) + +def doGrowth(argsList): + #CvUtil.pyPrint( "CvGameInterface.doGrowth" ) + return gameUtils().doGrowth(argsList) + +def doProduction(argsList): + #CvUtil.pyPrint( "CvGameInterface.doProduction" ) + return gameUtils().doProduction(argsList) + +def doCulture(argsList): + #CvUtil.pyPrint( "CvGameInterface.doCulture" ) + return gameUtils().doCulture(argsList) + +def doPlotCulture(argsList): + #CvUtil.pyPrint( "CvGameInterface.doPlotCulture" ) + return gameUtils().doPlotCulture(argsList) + +def doReligion(argsList): + #CvUtil.pyPrint( "CvGameInterface.doReligion" ) + return gameUtils().doReligion(argsList) + +def doGreatPeople(argsList): + #CvUtil.pyPrint( "CvGameInterface.doGreatPeople" ) + return gameUtils().doGreatPeople(argsList) + +def doMeltdown(argsList): + #CvUtil.pyPrint( "CvGameInterface.doMeltdown" ) + return gameUtils().doMeltdown(argsList) + +def doReviveActivePlayer(argsList): + return gameUtils().doReviveActivePlayer(argsList) + +def doPillageGold(argsList): + return gameUtils().doPillageGold(argsList) + +def doCityCaptureGold(argsList): + return gameUtils().doCityCaptureGold(argsList) + +def citiesDestroyFeatures(argsList): + return gameUtils().citiesDestroyFeatures(argsList) + +def canFoundCitiesOnWater(argsList): + return gameUtils().canFoundCitiesOnWater(argsList) + +def doCombat(argsList): + return gameUtils().doCombat(argsList) + +def getConscriptUnitType(argsList): + return gameUtils().getConscriptUnitType(argsList) + +def getCityFoundValue(argsList): + return gameUtils().getCityFoundValue(argsList) + +def canPickPlot(argsList): + return gameUtils().canPickPlot(argsList) + +def getUnitCostMod(argsList): + return gameUtils().getUnitCostMod(argsList) + +def getBuildingCostMod(argsList): + return gameUtils().getBuildingCostMod(argsList) + +def canUpgradeAnywhere(argsList): + return gameUtils().canUpgradeAnywhere(argsList) + +def getWidgetHelp(argsList): + return gameUtils().getWidgetHelp(argsList) + +def getUpgradePriceOverride(argsList): + return gameUtils().getUpgradePriceOverride(argsList) + +def getExperienceNeeded(argsList): + return gameUtils().getExperienceNeeded(argsList) \ No newline at end of file diff --git a/Mod/RB Mod/Assets/XML/Buildings/CIV4BuildingClassInfos.xml b/Mod/RB Mod/Assets/XML/Buildings/CIV4BuildingClassInfos.xml index d87a11a..e4d9743 100644 --- a/Mod/RB Mod/Assets/XML/Buildings/CIV4BuildingClassInfos.xml +++ b/Mod/RB Mod/Assets/XML/Buildings/CIV4BuildingClassInfos.xml @@ -1434,5 +1434,17 @@ BUILDING_INTERNET + + BUILDINGCLASS_QUAY + Quay + -1 + -1 + -1 + 0 + 0 + 0 + BUILDING_QUAY + + \ No newline at end of file diff --git a/Mod/RB Mod/Assets/XML/Buildings/CIV4BuildingInfos.xml b/Mod/RB Mod/Assets/XML/Buildings/CIV4BuildingInfos.xml index 9583d63..2c1d13f 100644 --- a/Mod/RB Mod/Assets/XML/Buildings/CIV4BuildingInfos.xml +++ b/Mod/RB Mod/Assets/XML/Buildings/CIV4BuildingInfos.xml @@ -132,7 +132,7 @@ 0 0 - 8 + 9 0 @@ -421,7 +421,7 @@ 0 0 0 - 800 + 500 100 -1 0 @@ -900,7 +900,7 @@ NONE NONE NONE - TECH_ECONOMICS + TECH_CORPORATION TECH_ENGINEERING NONE @@ -1093,8 +1093,8 @@ NONE NONE NONE - TECH_ECONOMICS - TECH_ENGINEERING + TECH_CORPORATION + TECH_MACHINERY NONE @@ -1955,6 +1955,18 @@ UNITCOMBAT_MOUNTED 4 + + UNITCOMBAT_MELEE + 2 + + + UNITCOMBAT_SIEGE + 2 + + + UNITCOMBAT_ARCHER + 2 + @@ -2930,7 +2942,7 @@ 0 1 0 - 100 + 80 0 100 0 @@ -3101,7 +3113,7 @@ 0 1 0 - 100 + 80 0 100 0 @@ -3240,7 +3252,7 @@ NONE 0 NONE - NONE + PROMOTION_MEDIC1 NONE NONE 0 @@ -3738,7 +3750,7 @@ NONE 0 NONE - PROMOTION_FLANKING1 + NONE NONE NONE 0 @@ -3849,7 +3861,12 @@ - + + + DOMAIN_SEA + 25 + + @@ -3868,6 +3885,177 @@ 0 0 + + BUILDINGCLASS_QUAY + BUILDING_QUAY + NONE + Quay + TXT_KEY_BUILDING_HARBOR_PEDIA + TXT_KEY_BUILDING_HARBOR_STRATEGY + ADVISOR_ECONOMY + ART_DEF_BUILDING_HARBOR + NONE + NONE + NONE + NONE + 0 + NONE + NONE + NONE + NONE + NONE + NONE + NONE + NONE + NONE + TECH_COMPASS + + NONE + + + + TRAIT_CHARISMATIC + 100 + + + + NONE + NONE + NONE + 0 + NONE + NONE + NONE + NONE + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + NONE + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 80 + 0 + 100 + 0 + 10 + 66 + 0 + 0 + 0 + 0 + 90 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + 0 + 1.0 + + 0 + 0 + 1 + + + + + + + + + + + + + + + + + + AS2D_BUILD_DRYDOCK + + + + + + + + + + + + + + + FLAVOR_GOLD + 10 + + + + 0 + 0 + 0 + 0 + BUILDINGCLASS_HARBOR BUILDING_HARBOR @@ -4294,7 +4482,7 @@ 0 0 0 - 180 + 120 0 100 0 @@ -4342,8 +4530,8 @@ 0 0 0 - 0 - 100 + 100 + 0 0 0 0 @@ -4427,12 +4615,7 @@ NONE - - - TRAIT_IMPERIALIST - 100 - - + NONE NONE @@ -4704,7 +4887,11 @@ - + + 0 + 4 + 0 + @@ -6933,7 +7120,7 @@ NONE NONE NONE - TECH_ASTRONOMY + TECH_GUNPOWDER TECH_MYSTICISM NONE @@ -6946,7 +7133,7 @@ NONE 0 NONE - NONE + PROMOTION_DRILL2 NONE NONE 0 @@ -7047,11 +7234,7 @@ 0 1000 - - 0 - 0 - 25 - + @@ -7629,7 +7812,12 @@ NONE - + + + TRAIT_CREATIVE + 100 + + NONE NONE @@ -7807,7 +7995,12 @@ NONE - + + + TRAIT_CREATIVE + 100 + + NONE NONE @@ -8028,7 +8221,7 @@ 0 0 0 - 200 + 150 0 100 0 @@ -8211,7 +8404,7 @@ 0 0 0 - 200 + 150 0 100 0 @@ -8287,7 +8480,7 @@ 0 - 35 + 40 @@ -8919,7 +9112,7 @@ 0 0 0 - 200 + 150 0 100 0 @@ -9574,7 +9767,12 @@ 20 - + + + SPECIALIST_ARTIST + 2 + + @@ -9637,7 +9835,7 @@ - TRAIT_CREATIVE + TRAIT_CHARISMATIC 100 @@ -9711,7 +9909,7 @@ 0 0 0 - 1 + 2 0 0 0 @@ -9758,7 +9956,24 @@ - + + + UNITCOMBAT_ARCHER + 1 + + + UNITCOMBAT_MELEE + 1 + + + UNITCOMBAT_MOUNTED + 1 + + + UNITCOMBAT_SIEGE + 1 + + @@ -9803,7 +10018,7 @@ - TRAIT_CREATIVE + TRAIT_CHARISMATIC 100 @@ -9904,11 +10119,7 @@ - - 0 - 0 - 3 - + 0 0 @@ -9924,26 +10135,21 @@ 5 - - - SPECIALIST_ARTIST - 2 - - + AS2D_BUILD_COLOSSEUM - - - BONUS_MUSIC - 1 - - + - + + + DOMAIN_LAND + 1 + + @@ -9987,7 +10193,7 @@ - TRAIT_CREATIVE + TRAIT_CHARISMATIC 100 @@ -10106,9 +10312,31 @@ AS2D_BUILD_COLOSSEUM - + + + BONUS_INCENSE + 1 + + - + + + UNITCOMBAT_ARCHER + 1 + + + UNITCOMBAT_MELEE + 1 + + + UNITCOMBAT_MOUNTED + 1 + + + UNITCOMBAT_SIEGE + 1 + + @@ -10153,7 +10381,7 @@ - TRAIT_CREATIVE + TRAIT_CHARISMATIC 100 @@ -10227,7 +10455,7 @@ 2 0 0 - 1 + 2 0 0 0 @@ -10274,7 +10502,24 @@ - + + + UNITCOMBAT_ARCHER + 1 + + + UNITCOMBAT_MELEE + 1 + + + UNITCOMBAT_MOUNTED + 1 + + + UNITCOMBAT_SIEGE + 1 + + @@ -11780,14 +12025,14 @@ 0 - BUILDINGCLASS_GROCER - BUILDING_AMERICAN_MALL + BUILDINGCLASS_BARRACKS + BUILDING_AMERICAN_ARMOURY NONE TXT_KEY_BUILDING_AMERICAN_MALL TXT_KEY_CHANGED_BUILDING_AMERICAN_MALL_PEDIA TXT_KEY_BUILDING_AMERICAN_MALL_STRATEGY ADVISOR_GROWTH - ART_DEF_BUILDING_AMERICAN_MALL + ART_DEF_BUILDING_ZULU_IKHANDA NONE NONE NONE @@ -11802,17 +12047,13 @@ NONE NONE NONE - TECH_GUILDS - - TECH_CURRENCY - NONE - NONE - + NONE + NONE - TRAIT_EXPANSIVE + TRAIT_AGGRESSIVE 100 @@ -11849,7 +12090,7 @@ 0 0 0 - 150 + 60 0 100 0 @@ -11915,69 +12156,42 @@ 0 - - - - 25 - + + 0 + 0 + 1 + + + 0 + 0 + 1000 + + - - - SPECIALIST_MERCHANT - 2 - - + - AS2D_BUILD_GROCER - - - BONUS_SPICES - 1 - - - BONUS_SUGAR - 1 - - - BONUS_WINE - 1 - - - BONUS_BANANA - 1 - - - - - BONUS_DEER - 1 - - - BONUS_SUGAR - 1 - - - BONUS_DRAMA - 1 - - - BONUS_MUSIC - 1 - - - BONUS_MOVIES - 1 - - + AS2D_BUILD_BARRACKS + + - - + + + UNITCOMBAT_MOUNTED + 2 + + + + + DOMAIN_LAND + 3 + + @@ -13272,11 +13486,16 @@ NONE NONE NONE - TECH_STEAM_POWER + TECH_REPLACEABLE_PARTS NONE - + + + TRAIT_FINANCIAL + 100 + + NONE NONE @@ -13291,7 +13510,7 @@ 0 0 1 - 1 + 0 0 0 0 @@ -13310,7 +13529,7 @@ 0 0 0 - 180 + 120 0 100 0 @@ -13371,12 +13590,10 @@ 1.0 0 + 2 1 - - 0 - 1 - + @@ -18853,7 +19070,7 @@ 0 0 0 - 200 + 150 50 -1 0 @@ -18861,7 +19078,7 @@ 0 0 0 - 4 + 0 0 90 0 @@ -18956,6 +19173,10 @@ BUILDINGCLASS_BARRACKS 1 + + BUILDINGCLASS_COLOSSEUM + 1 + @@ -19744,7 +19965,7 @@ 0 0 0 - 400 + 600 50 -1 0 @@ -20629,7 +20850,7 @@ NONE 0 NONE - PROMOTION_MEDIC1 + PROMOTION_MARCH NONE UNITCLASS_SCIENTIST 1 @@ -21964,13 +22185,13 @@ 10 0 1.0 - - - + 0 0 - 1 - + 2 + + + @@ -25432,7 +25653,7 @@ NONE 0 NONE - NONE + PROMOTION_DRILL1 NONE NONE 0 @@ -25477,7 +25698,7 @@ 0 0 0 - 0 + 1 0 0 0 @@ -26796,7 +27017,7 @@ BONUS_GOLD - 100 + 50 @@ -26843,7 +27064,7 @@ NONE ERA_ANCIENT NONE - TECH_SAILING + TECH_FISHING NONE @@ -26881,7 +27102,7 @@ 0 0 0 - 250 + 100 100 -1 0 diff --git a/Mod/RB Mod/Assets/XML/Civilizations/CIV4CivilizationInfos.xml b/Mod/RB Mod/Assets/XML/Civilizations/CIV4CivilizationInfos.xml index db4330c..ae2423a 100644 --- a/Mod/RB Mod/Assets/XML/Civilizations/CIV4CivilizationInfos.xml +++ b/Mod/RB Mod/Assets/XML/Civilizations/CIV4CivilizationInfos.xml @@ -7,6 +7,7 @@ + CIVILIZATION_AMERICA TXT_KEY_CIV_AMERICA_DESC TXT_KEY_CIV_AMERICA_SHORT_DESC @@ -82,8 +83,8 @@ - BUILDINGCLASS_GROCER - BUILDING_AMERICAN_MALL + BUILDINGCLASS_BARRACKS + BUILDING_AMERICAN_ARMOURY @@ -141,6 +142,7 @@ AS3D_AMERICA_ORDER + CIVILIZATION_ARABIA TXT_KEY_CIV_ARABIA_DESC TXT_KEY_CIV_ARABIA_SHORT_DESC @@ -220,7 +222,7 @@ 1 - TECH_MYSTICISM + TECH_HUNTING 1 @@ -243,6 +245,7 @@ AS3D_ARABIA_ORDER + CIVILIZATION_AZTEC TXT_KEY_CIV_AZTEC_DESC TXT_KEY_CIV_AZTEC_SHORT_DESC @@ -318,7 +321,7 @@ - TECH_MYSTICISM + TECH_THE_WHEEL 1 @@ -345,6 +348,7 @@ AS3D_AZTEC_ORDER + CIVILIZATION_BABYLON TXT_KEY_CIV_BABYLON_DESC TXT_KEY_CIV_BABYLON_SHORT_DESC @@ -451,6 +455,7 @@ AS3D_BABYLON_ORDER + CIVILIZATION_BYZANTIUM TXT_KEY_CIV_BYZANTIUM_DESC TXT_KEY_CIV_BYZANTIUM_SHORT_DESC @@ -538,7 +543,7 @@ 1 - TECH_MYSTICISM + TECH_AGRICULTURE 1 @@ -561,6 +566,7 @@ AS3D_BYZANTIUM_ORDER + CIVILIZATION_CARTHAGE TXT_KEY_CIV_CARTHAGE_DESC TXT_KEY_CIV_CARTHAGE_SHORT_DESC @@ -668,6 +674,7 @@ AS3D_CARTHAGE_ORDER + CIVILIZATION_CELT TXT_KEY_CIV_CELT_DESC TXT_KEY_CIV_CELT_SHORT_DESC @@ -756,7 +763,7 @@ 1 - TECH_MYSTICISM + TECH_FISHING 1 @@ -783,6 +790,7 @@ AS3D_CELTS_ORDER + CIVILIZATION_CHINA TXT_KEY_CIV_CHINA_DESC TXT_KEY_CIV_CHINA_SHORT_DESC @@ -897,6 +905,7 @@ AS3D_CHINA_ORDER + CIVILIZATION_EGYPT TXT_KEY_CIV_EGYPT_DESC TXT_KEY_CIV_EGYPT_SHORT_DESC @@ -1023,6 +1032,7 @@ AS3D_EGYPT_ORDER + CIVILIZATION_ENGLAND TXT_KEY_CIV_ENGLAND_DESC TXT_KEY_CIV_ENGLAND_SHORT_DESC @@ -1135,6 +1145,7 @@ AS3D_ENGLAND_ORDER + CIVILIZATION_ETHIOPIA TXT_KEY_CIV_ETHIOPIA_DESC TXT_KEY_CIV_ETHIOPIA_SHORT_DESC @@ -1212,7 +1223,7 @@ - TECH_HUNTING + TECH_AGRICULTURE 1 @@ -1239,6 +1250,7 @@ AS3D_ETHIOPIA_ORDER + CIVILIZATION_FRANCE TXT_KEY_CIV_FRANCE_DESC TXT_KEY_CIV_FRANCE_SHORT_DESC @@ -1353,6 +1365,7 @@ AS3D_FRANCE_ORDER + CIVILIZATION_GERMANY TXT_KEY_CIV_GERMANY_DESC TXT_KEY_CIV_GERMANY_SHORT_DESC @@ -1476,6 +1489,7 @@ AS3D_GERMANY_ORDER + CIVILIZATION_GREECE TXT_KEY_CIV_GREECE_DESC TXT_KEY_CIV_GREECE_SHORT_DESC @@ -1591,6 +1605,7 @@ AS3D_GREECE_ORDER + CIVILIZATION_HOLY_ROMAN TXT_KEY_CIV_HOLY_ROMAN_DESC TXT_KEY_CIV_HOLY_ROMAN_SHORT_DESC @@ -1676,7 +1691,7 @@ - TECH_MYSTICISM + TECH_MINING 1 @@ -1703,6 +1718,7 @@ AS3D_HOLY_ROMAN_ORDER + CIVILIZATION_INCA TXT_KEY_CIV_INCA_DESC TXT_KEY_CIV_INCA_SHORT_DESC @@ -1776,11 +1792,11 @@ - TECH_AGRICULTURE + TECH_THE_WHEEL 1 - TECH_MYSTICISM + TECH_MINING 1 @@ -1803,6 +1819,7 @@ AS3D_INCA_ORDER + CIVILIZATION_INDIA TXT_KEY_CIV_INDIA_DESC TXT_KEY_CIV_INDIA_SHORT_DESC @@ -1939,7 +1956,7 @@ - TECH_MYSTICISM + TECH_FISHING 1 @@ -1970,6 +1987,7 @@ AS3D_INDIA_ORDER + CIVILIZATION_JAPAN TXT_KEY_CIV_JAPAN_DESC TXT_KEY_CIV_JAPAN_SHORT_DESC @@ -2071,6 +2089,7 @@ AS3D_JAPAN_ORDER + CIVILIZATION_KHMER TXT_KEY_CIV_KHMER_DESC TXT_KEY_CIV_KHMER_SHORT_DESC @@ -2178,6 +2197,7 @@ AS3D_KHMER_ORDER + CIVILIZATION_KOREA TXT_KEY_CIV_KOREA_DESC TXT_KEY_CIV_KOREA_SHORT_DESC @@ -2274,6 +2294,7 @@ AS3D_KOREA_ORDER + CIVILIZATION_MALI TXT_KEY_CIV_MALI_DESC TXT_KEY_CIV_MALI_SHORT_DESC @@ -2370,6 +2391,7 @@ AS3D_MALI_ORDER + CIVILIZATION_MAYA TXT_KEY_CIV_MAYA_DESC TXT_KEY_CIV_MAYA_SHORT_DESC @@ -2457,7 +2479,7 @@ 1 - TECH_MYSTICISM + TECH_THE_WHEEL 1 @@ -2480,6 +2502,7 @@ AS3D_MAYA_ORDER + CIVILIZATION_MONGOL TXT_KEY_CIV_MONGOL_DESC TXT_KEY_CIV_MONGOL_SHORT_DESC @@ -2583,6 +2606,7 @@ AS3D_MONGOL_ORDER + CIVILIZATION_NATIVE_AMERICA TXT_KEY_CIV_NATIVE_AMERICA_DESC TXT_KEY_CIV_NATIVE_AMERICA_SHORT_DESC @@ -2672,11 +2696,11 @@ - TECH_AGRICULTURE + TECH_THE_WHEEL 1 - TECH_FISHING + TECH_HUNTING 1 @@ -2699,6 +2723,7 @@ AS3D_NATIVE_AMERICA_ORDER + CIVILIZATION_NETHERLANDS TXT_KEY_CIV_NETHERLANDS_DESC TXT_KEY_CIV_NETHERLANDS_SHORT_DESC @@ -2810,6 +2835,7 @@ AS3D_NETHERLANDS_ORDER + CIVILIZATION_OTTOMAN TXT_KEY_CIV_OTTOMAN_DESC TXT_KEY_CIV_OTTOMAN_SHORT_DESC @@ -2889,7 +2915,7 @@ 1 - TECH_AGRICULTURE + TECH_HUNTING 1 @@ -2916,6 +2942,7 @@ AS3D_OTTOMAN_ORDER + CIVILIZATION_PERSIA TXT_KEY_CIV_PERSIA_DESC TXT_KEY_CIV_PERSIA_SHORT_DESC @@ -3051,6 +3078,7 @@ AS3D_PERSIA_ORDER + CIVILIZATION_PORTUGAL TXT_KEY_CIV_PORTUGAL_DESC TXT_KEY_CIV_PORTUGAL_SHORT_DESC @@ -3162,6 +3190,7 @@ AS3D_PORTUGAL_ORDER + CIVILIZATION_ROME TXT_KEY_CIV_ROME_DESC TXT_KEY_CIV_ROME_SHORT_DESC @@ -3260,7 +3289,7 @@ 1 - TECH_MINING + TECH_THE_WHEEL 1 @@ -3287,6 +3316,7 @@ AS3D_ROME_ORDER + CIVILIZATION_RUSSIA TXT_KEY_CIV_RUSSIA_DESC TXT_KEY_CIV_RUSSIA_SHORT_DESC @@ -3399,6 +3429,7 @@ AS3D_RUSSIA_ORDER + CIVILIZATION_SPAIN TXT_KEY_CIV_SPAIN_DESC TXT_KEY_CIV_SPAIN_SHORT_DESC @@ -3483,7 +3514,7 @@ 1 - TECH_MYSTICISM + TECH_THE_WHEEL 1 @@ -3506,6 +3537,7 @@ AS3D_SPAIN_ORDER + CIVILIZATION_SUMERIA TXT_KEY_CIV_SUMERIA_DESC TXT_KEY_CIV_SUMERIA_SHORT_DESC @@ -3609,6 +3641,7 @@ AS3D_SUMERIA_ORDER + CIVILIZATION_VIKING TXT_KEY_CIV_VIKING_DESC TXT_KEY_CIV_VIKING_SHORT_DESC @@ -3714,6 +3747,7 @@ AS3D_VIKING_ORDER + CIVILIZATION_ZULU TXT_KEY_CIV_ZULU_DESC TXT_KEY_CIV_ZULU_SHORT_DESC @@ -3816,6 +3850,7 @@ AS3D_ZULU_ORDER + CIVILIZATION_MINOR TXT_KEY_CIV_MINOR_DESC TXT_KEY_CIV_MINOR_SHORT_DESC @@ -3952,6 +3987,7 @@ + CIVILIZATION_BARBARIAN TXT_KEY_CIV_BARBARIAN_DESC TXT_KEY_CIV_BARBARIAN_SHORT_DESC diff --git a/Mod/RB Mod/Assets/XML/Civilizations/CIV4CivilizationsSchema.xml b/Mod/RB Mod/Assets/XML/Civilizations/CIV4CivilizationsSchema.xml index e756a8e..8818ab5 100644 --- a/Mod/RB Mod/Assets/XML/Civilizations/CIV4CivilizationsSchema.xml +++ b/Mod/RB Mod/Assets/XML/Civilizations/CIV4CivilizationsSchema.xml @@ -433,6 +433,7 @@ + diff --git a/Mod/RB Mod/Assets/XML/Civilizations/CIV4TraitInfos.xml b/Mod/RB Mod/Assets/XML/Civilizations/CIV4TraitInfos.xml index 0b48b32..37d01ff 100644 --- a/Mod/RB Mod/Assets/XML/Civilizations/CIV4TraitInfos.xml +++ b/Mod/RB Mod/Assets/XML/Civilizations/CIV4TraitInfos.xml @@ -156,7 +156,7 @@ 0 0 - 2 + 1 @@ -181,7 +181,7 @@ 0 0 - 2 + 3 @@ -221,7 +221,7 @@ -1 0 0 - -25 + -20 0 0 0 @@ -260,6 +260,10 @@ PROMOTION_CITY_GARRISON1 1 + + PROMOTION_DRILL1 + 1 + diff --git a/Mod/RB Mod/Assets/XML/GameInfo/CIV4CivicInfos.xml b/Mod/RB Mod/Assets/XML/GameInfo/CIV4CivicInfos.xml index 1327778..89ba9dc 100644 --- a/Mod/RB Mod/Assets/XML/GameInfo/CIV4CivicInfos.xml +++ b/Mod/RB Mod/Assets/XML/GameInfo/CIV4CivicInfos.xml @@ -2,41 +2,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CIVICOPTION_GOVERNMENT @@ -98,7 +66,28 @@ + + + SPECIALIST_ARTIST + 0 + + + SPECIALIST_SCIENTIST + 0 + + + SPECIALIST_MERCHANT + 0 + + + + + + + + + TXT_KEY_CIVIC_WE_LOVE_DESPOT @@ -163,7 +152,15 @@ + + + + + + + + TXT_KEY_CIVIC_WE_LOVE_MONARCH @@ -232,7 +229,15 @@ + + + + + + + + TXT_KEY_CIVIC_WE_LOVE_PRIME_MINISTER @@ -297,7 +302,15 @@ + + + + + + + + TXT_KEY_CIVIC_WE_LOVE_DICTATOR @@ -367,7 +380,15 @@ + + + + + + + + @@ -379,7 +400,7 @@ - TXT_KEY_CIVIC_WE_LOVE_PRESIDENT + TXT_KEY_CIVIC_WE_LOVE_SMIZMAR CIVICOPTION_LEGAL @@ -441,7 +462,28 @@ + + + SPECIALIST_ARTIST + 0 + + + SPECIALIST_SCIENTIST + 0 + + + SPECIALIST_MERCHANT + 0 + + + + + + + + + @@ -455,7 +497,7 @@ TECH_FEUDALISM 1 - UPKEEP_MEDIUM + UPKEEP_LOW 0 0 0 @@ -469,10 +511,10 @@ 0 0 0 - 5 - 5 - 10 - 10 + 10 + 10 + 20 + 20 0 0 0 @@ -506,7 +548,15 @@ + + + + + + + + @@ -575,7 +625,15 @@ + + + + + + + + @@ -650,7 +708,15 @@ 2 + + + + + + + + @@ -662,7 +728,7 @@ TXT_KEY_CIVIC_ENVIRONMENTALISM_PEDIA TXT_KEY_CIVIC_ENVIRONMENTALISM_STRATEGY - TECH_LIBERALISM + TECH_ECONOMICS 1 UPKEEP_LOW 0 @@ -673,7 +739,7 @@ 0 0 0 - 0 + 3 0 0 0 @@ -719,17 +785,17 @@ + + + + + + + + - - IMPROVEMENT_FARM - - 0 - 0 - 1 - - IMPROVEMENT_PASTURE @@ -739,11 +805,11 @@ - IMPROVEMENT_FOREST_PRESERVE + IMPROVEMENT_FARM 0 0 - 2 + 1 @@ -809,7 +875,15 @@ + + + + + + + + @@ -879,7 +953,15 @@ + + + + + + + + @@ -893,7 +975,7 @@ TECH_FEUDALISM 1 - UPKEEP_LOW + UPKEEP_MEDIUM 0 0 0 @@ -944,19 +1026,32 @@ + + + SPECIALIST_ARTIST + 2 + + + SPECIALIST_SCIENTIST + 2 + + + SPECIALIST_MERCHANT + 2 + + + + + + + + + - IMPROVEMENT_WINDMILL - - 0 - 1 - 0 - - - - IMPROVEMENT_WATERMILL + IMPROVEMENT_MINE 0 1 @@ -975,7 +1070,7 @@ TECH_CODE_OF_LAWS 1 - UPKEEP_MEDIUM + UPKEEP_HIGH 0 0 0 @@ -1039,7 +1134,15 @@ + + + + + + + + @@ -1060,9 +1163,9 @@ TXT_KEY_CIVIC_EMANCIPATION_PEDIA TXT_KEY_CIVIC_EMANCIPATION_STRATEGY - TECH_DEMOCRACY + TECH_BANKING 1 - UPKEEP_LOW + UPKEEP_MEDIUM 0 0 0 @@ -1074,7 +1177,7 @@ 0 0 0 - 100 + 0 0 0 0 @@ -1095,7 +1198,7 @@ 0 0 0 - 400 + 0 0 0 0 @@ -1113,9 +1216,79 @@ + + + SPECIALIST_ARTIST + 2 + + + SPECIALIST_SCIENTIST + 2 + + + SPECIALIST_MERCHANT + 2 + + + + + + + + + - + + + IMPROVEMENT_MINE + + 0 + 0 + 1 + + + + IMPROVEMENT_WINDMILL + + 0 + 1 + 0 + + + + IMPROVEMENT_WATERMILL + + 0 + 1 + 0 + + + + IMPROVEMENT_COTTAGE + + 0 + 0 + 1 + + + + IMPROVEMENT_HAMLET + + 0 + 0 + 1 + + + + IMPROVEMENT_VILLAGE + + 0 + 0 + 1 + + + @@ -1178,7 +1351,15 @@ + + + + + + + + @@ -1190,9 +1371,9 @@ TXT_KEY_CIVIC_MERCANTILISM_PEDIA TXT_KEY_CIVIC_MERCANTILISM_STRATEGY - TECH_BANKING + TECH_LIBERALISM 1 - UPKEEP_MEDIUM + UPKEEP_HIGH 0 0 0 @@ -1220,9 +1401,9 @@ 0 0 0 - 1 + 2 0 - 1 + 0 0 0 0 @@ -1243,7 +1424,15 @@ + + + + + + + + @@ -1312,7 +1501,15 @@ + + + + + + + + @@ -1326,7 +1523,7 @@ TECH_UTOPIA 1 - UPKEEP_MEDIUM + UPKEEP_HIGH 0 0 0 @@ -1381,7 +1578,15 @@ + + + + + + + + @@ -1410,9 +1615,9 @@ TXT_KEY_CIVIC_FREE_SPEECH_PEDIA TXT_KEY_CIVIC_FREE_SPEECH_STRATEGY - TECH_SCIENTIFIC_METHOD + TECH_CONSTITUTION 1 - UPKEEP_LOW + UPKEEP_MEDIUM 0 0 0 @@ -1424,7 +1629,7 @@ 0 0 0 - 0 + 100 0 0 0 @@ -1457,17 +1662,30 @@ - 0 + 15 0 100 - + + + HURRY_GOLD + 1 + + + + + + + + + + @@ -1475,7 +1693,15 @@ 0 0 - 2 + 3 + + + + IMPROVEMENT_VILLAGE + + 0 + 0 + 1 @@ -1541,7 +1767,15 @@ + + + + + + + + @@ -1611,7 +1845,15 @@ + + + + + + + + @@ -1676,7 +1918,15 @@ + + + + + + + + @@ -1741,7 +1991,15 @@ + + + + + + + + @@ -1810,7 +2068,15 @@ + + + + + + + + diff --git a/Mod/RB Mod/Assets/XML/GameInfo/CIV4EspionageMissionInfo.xml b/Mod/RB Mod/Assets/XML/GameInfo/CIV4EspionageMissionInfo.xml index fac7f49..c99a5ac 100644 --- a/Mod/RB Mod/Assets/XML/GameInfo/CIV4EspionageMissionInfo.xml +++ b/Mod/RB Mod/Assets/XML/GameInfo/CIV4EspionageMissionInfo.xml @@ -181,285 +181,5 @@ 0 0 - - ESPIONAGEMISSION_DESTROY_IMPROVEMENT - TXT_KEY_ESPIONAGE_DESTROY_IMPROVEMENT - 150 - 0 - 0 - 0 - 1 - NONE - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - ESPIONAGEMISSION_DESTROY_BUILDING - TXT_KEY_ESPIONAGE_DESTROY_BUILDING - 0 - 0 - 1 - 1 - 0 - NONE - 0 - 0 - 0 - 0 - 0 - 0 - 10 - 1000 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - ESPIONAGEMISSION_DESTROY_PROJECT - TXT_KEY_ESPIONAGE_DESTROY_PROJECT - 0 - 0 - 1 - 1 - 0 - NONE - 0 - 0 - 0 - 0 - 0 - 0 - 25 - 0 - 0 - 1000 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - ESPIONAGEMISSION_STEAL_TREASURY - TXT_KEY_ESPIONAGE_STEAL_TREASURY - 600 - 0 - 0 - 1 - 0 - NONE - 0 - 0 - 0 - 0 - 0 - 0 - 25 - 0 - 0 - 0 - 0 - 0 - 0 - 100 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - ESPIONAGEMISSION_CITY_INSERT_CULTURE - TXT_KEY_ESPIONAGE_CITY_INSERT_CULTURE - 0 - 0 - 0 - 1 - 0 - NONE - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 5 - 600 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - ESPIONAGEMISSION_CITY_POISON_WATER - TXT_KEY_ESPIONAGE_CITY_POISON_WATER - 2400 - 0 - 0 - 1 - 0 - NONE - 0 - 0 - 0 - 0 - 0 - 0 - -50 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 8 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - ESPIONAGEMISSION_CITY_UNHAPPINESS - TXT_KEY_ESPIONAGE_CITY_UNHAPPINESS - 240 - 0 - 0 - 1 - 0 - NONE - 0 - 0 - 0 - 0 - 0 - 0 - -50 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 8 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - ESPIONAGEMISSION_BUY_TECH - TXT_KEY_ESPIONAGE_BUY_TECH - 0 - 0 - 1 - 1 - 0 - NONE - 0 - 0 - 0 - 0 - 0 - 0 - 25 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 100 - 0 - 0 - 0 - 0 - 0 - \ No newline at end of file diff --git a/Mod/RB Mod/Assets/XML/GameInfo/CIV4GameInfoSchema.xml b/Mod/RB Mod/Assets/XML/GameInfo/CIV4GameInfoSchema.xml new file mode 100644 index 0000000..a6e047a --- /dev/null +++ b/Mod/RB Mod/Assets/XML/GameInfo/CIV4GameInfoSchema.xml @@ -0,0 +1,1434 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mod/RB Mod/Assets/XML/GameInfo/CIV4GameOptionInfos.xml b/Mod/RB Mod/Assets/XML/GameInfo/CIV4GameOptionInfos.xml new file mode 100644 index 0000000..610d868 --- /dev/null +++ b/Mod/RB Mod/Assets/XML/GameInfo/CIV4GameOptionInfos.xml @@ -0,0 +1,185 @@ + + + + + + + + + + GAMEOPTION_ADVANCED_START + TXT_KEY_GAME_OPTION_ADVANCED_START + TXT_KEY_GAME_OPTION_ADVANCED_START_HELP + 0 + 1 + + + GAMEOPTION_NO_CITY_RAZING + TXT_KEY_GAME_OPTION_NO_CITY_RAZING + TXT_KEY_GAME_OPTION_NO_CITY_RAZING_HELP + 0 + 1 + + + GAMEOPTION_NO_CITY_FLIPPING + TXT_KEY_GAME_OPTION_NO_CITY_FLIPPING + TXT_KEY_GAME_OPTION_NO_CITY_FLIPPING_HELP + 0 + 1 + + + GAMEOPTION_FLIPPING_AFTER_CONQUEST + TXT_KEY_GAME_OPTION_FLIPPING_AFTER_CONQUEST + TXT_KEY_GAME_OPTION_FLIPPING_AFTER_CONQUEST_HELP + 0 + 1 + + + GAMEOPTION_NO_BARBARIANS + TXT_KEY_GAME_OPTION_NO_BARBARIANS + TXT_KEY_GAME_OPTION_NO_BARBARIANS_HELP + 0 + 1 + + + GAMEOPTION_RAGING_BARBARIANS + TXT_KEY_GAME_OPTION_RAGING_BARBARIANS + TXT_KEY_GAME_OPTION_RAGING_BARBARIANS_HELP + 0 + 1 + + + GAMEOPTION_AGGRESSIVE_AI + TXT_KEY_GAME_OPTION_AGGRESSIVE_AI + TXT_KEY_GAME_OPTION_AGGRESSIVE_AI_HELP + 0 + 1 + + + GAMEOPTION_LEAD_ANY_CIV + TXT_KEY_GAME_OPTION_LEAD_ANY_CIV + TXT_KEY_GAME_OPTION_LEAD_ANY_CIV_HELP + 0 + 1 + + + GAMEOPTION_RANDOM_PERSONALITIES + TXT_KEY_GAME_OPTION_RANDOM_PERSONALITIES + TXT_KEY_GAME_OPTION_RANDOM_PERSONALITIES_HELP + 0 + 1 + + + GAMEOPTION_PICK_RELIGION + TXT_KEY_GAME_OPTION_PICK_RELIGION + TXT_KEY_GAME_OPTION_PICK_RELIGION_HELP + 0 + 1 + + + GAMEOPTION_NO_TECH_TRADING + TXT_KEY_GAME_OPTION_NO_TECH_TRADING + TXT_KEY_GAME_OPTION_NO_TECH_TRADING_HELP + 0 + 1 + + + GAMEOPTION_NO_TECH_BROKERING + TXT_KEY_GAME_OPTION_NO_TECH_BROKERING + TXT_KEY_GAME_OPTION_NO_TECH_BROKERING_HELP + 0 + 1 + + + GAMEOPTION_PERMANENT_ALLIANCES + TXT_KEY_GAME_OPTION_PERMANENT_ALLIANCES + TXT_KEY_GAME_OPTION_PERMANENT_ALLIANCES_HELP + 0 + 1 + + + GAMEOPTION_ALWAYS_WAR + TXT_KEY_GAME_OPTION_ALWAYS_WAR + TXT_KEY_GAME_OPTION_ALWAYS_WAR_HELP + 0 + 1 + + + GAMEOPTION_ALWAYS_PEACE + TXT_KEY_MP_OPTION_ALWAYS_PEACE + TXT_KEY_MP_OPTION_ALWAYS_PEACE_HELP + 0 + 1 + + + GAMEOPTION_ONE_CITY_CHALLENGE + TXT_KEY_GAME_OPTION_ONE_CITY_CHALLENGE + TXT_KEY_GAME_OPTION_ONE_CITY_CHALLENGE_HELP + 0 + 1 + + + GAMEOPTION_NO_CHANGING_WAR_PEACE + TXT_KEY_GAME_OPTION_NO_CHANGING_WAR_PEACE + TXT_KEY_GAME_OPTION_NO_CHANGING_WAR_PEACE_HELP + 0 + 1 + + + GAMEOPTION_NEW_RANDOM_SEED + TXT_KEY_GAME_OPTION_NEW_RANDOM_SEED + TXT_KEY_GAME_OPTION_NEW_RANDOM_SEED_HELP + 0 + 1 + + + GAMEOPTION_LOCK_MODS + TXT_KEY_GAME_OPTION_LOCK_MODS + TXT_KEY_GAME_OPTION_LOCK_MODS_HELP + 0 + 1 + + + GAMEOPTION_COMPLETE_KILLS + TXT_KEY_GAME_OPTION_COMPLETE_KILLS + TXT_KEY_GAME_OPTION_COMPLETE_KILLS_HELP + 0 + 1 + + + GAMEOPTION_NO_VASSAL_STATES + TXT_KEY_GAME_OPTION_NO_VASSAL_STATES + TXT_KEY_GAME_OPTION_NO_VASSAL_STATES_HELP + 0 + 1 + + + GAMEOPTION_NO_GOODY_HUTS + TXT_KEY_GAME_OPTION_NO_GOODY_HUTS + TXT_KEY_GAME_OPTION_NO_GOODY_HUTS_HELP + 0 + 1 + + + GAMEOPTION_NO_EVENTS + TXT_KEY_GAME_OPTION_NO_EVENTS + TXT_KEY_GAME_OPTION_NO_EVENTS_HELP + 0 + 1 + + + GAMEOPTION_NO_ESPIONAGE + TXT_KEY_GAME_OPTION_NO_ESPIONAGE + TXT_KEY_GAME_OPTION_NO_ESPIONAGE_HELP + 0 + 1 + + + GAMEOPTION_NO_CITY_TRADING + TXT_KEY_GAME_OPTION_NO_CITY_TRADING + TXT_KEY_GAME_OPTION_NO_CITY_TRADING_HELP + 0 + 1 + + + diff --git a/Mod/RB Mod/Assets/XML/GameInfo/CIV4GameSpeedInfo.xml b/Mod/RB Mod/Assets/XML/GameInfo/CIV4GameSpeedInfo.xml new file mode 100644 index 0000000..f2e6fc2 --- /dev/null +++ b/Mod/RB Mod/Assets/XML/GameInfo/CIV4GameSpeedInfo.xml @@ -0,0 +1,251 @@ + + + + + + + + + + + GAMESPEED_MARATHON + TXT_KEY_GAMESPEED_MARATHON + TXT_KEY_GAMESPEED_MARATHON_HELP + 300 + 200 + 300 + 300 + 300 + 300 + 300 + 300 + 300 + 200 + 400 + 300 + 300 + 300 + 300 + 300 + 200 + 33 + 300 + 10 + -270 + 300 + + + 180 + 100 + + + 120 + 300 + + + 60 + 170 + + + 24 + 201 + + + 12 + 129 + + + 6 + 180 + + + 3 + 264 + + + 1 + 156 + + + + + GAMESPEED_EPIC + TXT_KEY_GAMESPEED_EPIC + TXT_KEY_GAMESPEED_EPIC_HELP + 150 + 150 + 150 + 150 + 150 + 150 + 150 + 150 + 150 + 150 + 150 + 150 + 150 + 150 + 150 + 150 + 125 + 66 + 150 + 20 + -135 + 150 + + + 300 + 140 + + + 180 + 90 + + + 120 + 40 + + + 60 + 90 + + + 24 + 70 + + + 12 + 100 + + + 6 + 220 + + + + + GAMESPEED_NORMAL + TXT_KEY_GAMESPEED_NORMAL + TXT_KEY_GAMESPEED_NORMAL_HELP + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 100 + 30 + -90 + 100 + + + 480 + 75 + + + 300 + 60 + + + 240 + 25 + + + 120 + 50 + + + 60 + 60 + + + 24 + 50 + + + 12 + 120 + + + 6 + 60 + + + + + GAMESPEED_QUICK + TXT_KEY_GAMESPEED_QUICK + TXT_KEY_GAMESPEED_QUICK_HELP + 67 + 67 + 67 + 67 + 67 + 66 + 67 + 67 + 67 + 67 + 67 + 67 + 67 + 67 + 67 + 67 + 80 + 150 + 67 + 45 + -60 + 67 + + + 720 + 50 + + + 480 + 30 + + + 360 + 20 + + + 240 + 30 + + + 120 + 25 + + + 60 + 40 + + + 24 + 65 + + + 12 + 70 + + + + + diff --git a/Mod/RB Mod/Assets/XML/GameInfo/CIV4ProjectInfo.xml b/Mod/RB Mod/Assets/XML/GameInfo/CIV4ProjectInfo.xml index bc872f6..e2dd734 100644 --- a/Mod/RB Mod/Assets/XML/GameInfo/CIV4ProjectInfo.xml +++ b/Mod/RB Mod/Assets/XML/GameInfo/CIV4ProjectInfo.xml @@ -7,38 +7,6 @@ - - PROJECT_MANHATTAN_PROJECT - TXT_KEY_PROJECT_MANHATTAN_PROJECT - TXT_KEY_PROJECT_MANHATTAN_PROJECT_PEDIA - TXT_KEY_PROJECT_MANHATTAN_PROJECT_STRATEGY - NONE - TECH_FISSION - NONE - 1 - -1 - 1500 - 0 - 0 - NONE - SPECIALBUILDING_BOMB_SHELTER - 0 - 1 - - - - - 0 - 0 - - - BONUS_URANIUM - 100 - - - - ART_DEF_MOVIE_MANHATTAN_PROJECT - PROJECT_SDI TXT_KEY_PROJECT_SDI @@ -46,14 +14,14 @@ TXT_KEY_PROJECT_SDI_STRATEGY NONE TECH_LASER - PROJECT_MANHATTAN_PROJECT + NONE -1 1 1000 0 0 NONE - NONE + SPECIALBUILDING_BOMB_SHELTER 0 0 @@ -65,7 +33,7 @@ BONUS_ALUMINUM - 100 + 50 @@ -97,7 +65,7 @@ BONUS_ALUMINUM - 100 + 50 @@ -139,7 +107,7 @@ BONUS_COPPER - 100 + 50 @@ -181,7 +149,7 @@ BONUS_COPPER - 100 + 50 @@ -260,7 +228,7 @@ BONUS_ALUMINUM - 100 + 50 @@ -349,7 +317,7 @@ BONUS_ALUMINUM - 100 + 50 @@ -396,7 +364,7 @@ BONUS_ALUMINUM - 100 + 50 diff --git a/Mod/RB Mod/Assets/XML/GameInfo/CIV4SpecialistInfos.xml b/Mod/RB Mod/Assets/XML/GameInfo/CIV4SpecialistInfos.xml new file mode 100644 index 0000000..3d09c6a --- /dev/null +++ b/Mod/RB Mod/Assets/XML/GameInfo/CIV4SpecialistInfos.xml @@ -0,0 +1,386 @@ + + + + + + + + + + SPECIALIST_CITIZEN + TXT_KEY_SPECIALIST_CITIZEN + TXT_KEY_CONCEPT_SPECIALISTS_PEDIA + TXT_KEY_SPECIALIST_CITIZEN_STRATEGY + + Art/Interface/MainScreen/CityScreen/Citizen.dds + 1 + NONE + 0 + + 0 + 1 + 0 + + + 0 + + + 0 + 0 + 0 + 0 + + + + SPECIALIST_PRIEST + TXT_KEY_SPECIALIST_PRIEST + TXT_KEY_CONCEPT_SPECIALISTS_PEDIA + TXT_KEY_SPECIALIST_PRIEST_STRATEGY + + Art/Interface/MainScreen/CityScreen/Priest.dds + 1 + UNITCLASS_PROPHET + 3 + + 0 + 1 + 0 + + + 1 + 0 + 0 + + 0 + + + 0 + 0 + 0 + 0 + + + + SPECIALIST_ARTIST + TXT_KEY_SPECIALIST_ARTIST + TXT_KEY_CONCEPT_SPECIALISTS_PEDIA + TXT_KEY_SPECIALIST_ARTIST_STRATEGY + + Art/Interface/MainScreen/CityScreen/Artist.dds + 1 + UNITCLASS_ARTIST + 3 + + + 0 + 1 + 4 + + 0 + + + 0 + 0 + 0 + 0 + + + + SPECIALIST_SCIENTIST + TXT_KEY_SPECIALIST_SCIENTIST + TXT_KEY_CONCEPT_SPECIALISTS_PEDIA + TXT_KEY_SPECIALIST_SCIENTIST_STRATEGY + + Art/Interface/MainScreen/CityScreen/scientist.dds + 1 + UNITCLASS_SCIENTIST + 3 + + + 0 + 3 + 0 + + 0 + + + 0 + 0 + 0 + 0 + + + + SPECIALIST_MERCHANT + TXT_KEY_SPECIALIST_MERCHANT + TXT_KEY_CONCEPT_SPECIALISTS_PEDIA + TXT_KEY_SPECIALIST_MERCHANT_STRATEGY + + Art/Interface/MainScreen/CityScreen/merchant.dds + 1 + UNITCLASS_MERCHANT + 3 + + + 3 + 0 + 0 + + 0 + + + 0 + 0 + 0 + 0 + + + + SPECIALIST_ENGINEER + TXT_KEY_SPECIALIST_ENGINEER + TXT_KEY_CONCEPT_SPECIALISTS_PEDIA + TXT_KEY_SPECIALIST_ENGINEER_STRATEGY + + Art/Interface/MainScreen/CityScreen/engineer.dds + 1 + UNITCLASS_ENGINEER + 3 + + 0 + 2 + 0 + + + 0 + + + 0 + 0 + 0 + 0 + + + + SPECIALIST_SPY + TXT_KEY_UNIT_SPY + TXT_KEY_CONCEPT_GREAT_SPY_PEDIA + TXT_KEY_SPECIALIST_SPY_STRATEGY + + ,Art/Interface/Buttons/TechTree/Corporation.dds,Art/Interface/Buttons/Beyond_the_Sword_Atlas.dds,5,14 + 1 + UNITCLASS_GREAT_SPY + 3 + + + 0 + 1 + 0 + 4 + + 0 + + + 0 + 0 + 0 + 0 + + + + SPECIALIST_GREAT_PRIEST + TXT_KEY_SPECIALIST_GREAT_PRIEST + TXT_KEY_CONCEPT_GREAT_PEOPLE_PEDIA + TXT_KEY_SPECIALIST_GREAT_PRIEST_STRATEGY + + Art/Interface/MainScreen/CityScreen/Great_Priest.dds + 0 + NONE + 0 + + 0 + 2 + 0 + + + 5 + 0 + 0 + + 0 + + + 0 + 0 + 0 + 0 + + + + SPECIALIST_GREAT_ARTIST + TXT_KEY_SPECIALIST_GREAT_ARTIST + TXT_KEY_CONCEPT_GREAT_PEOPLE_PEDIA + TXT_KEY_SPECIALIST_GREAT_ARTIST_STRATEGY + + Art/Interface/MainScreen/CityScreen/Great_Artist.dds + 0 + NONE + 0 + + + 3 + 3 + 6 + + 0 + + + 0 + 0 + 0 + 0 + + + + SPECIALIST_GREAT_SCIENTIST + TXT_KEY_SPECIALIST_GREAT_SCIENTIST + TXT_KEY_CONCEPT_GREAT_PEOPLE_PEDIA + TXT_KEY_SPECIALIST_GREAT_SCIENTIST_STRATEGY + + Art/Interface/MainScreen/CityScreen/Great_Scientist.dds + 0 + NONE + 0 + + 0 + 1 + 0 + + + 0 + 6 + 0 + + 0 + + + 0 + 0 + 0 + 0 + + + + SPECIALIST_GREAT_MERCHANT + TXT_KEY_SPECIALIST_GREAT_MERCHANT + TXT_KEY_CONCEPT_GREAT_PEOPLE_PEDIA + TXT_KEY_SPECIALIST_GREAT_MERCHANT_STRATEGY + + Art/Interface/MainScreen/CityScreen/Great_Merchant.dds + 0 + NONE + 0 + + 1 + 0 + 0 + + + 6 + 0 + 0 + + 0 + + + 0 + 0 + 0 + 0 + + + + SPECIALIST_GREAT_ENGINEER + TXT_KEY_SPECIALIST_GREAT_ENGINEER + TXT_KEY_CONCEPT_GREAT_PEOPLE_PEDIA + TXT_KEY_SPECIALIST_GREAT_ENGINEER_STRATEGY + + Art/Interface/MainScreen/CityScreen/Great_Engineer.dds + 0 + NONE + 0 + + 0 + 3 + 0 + + + 0 + 3 + 0 + + 0 + + + 0 + 0 + 0 + 0 + + + + SPECIALIST_GREAT_GENERAL + TXT_KEY_SPECIALIST_GREAT_GENERAL + TXT_KEY_CONCEPT_GREAT_GENERALS_PEDIA + TXT_KEY_SPECIALIST_GREAT_GENERAL_STRATEGY + + ,Art/Interface/MainScreen/CityScreen/Great_Engineer.dds,Art/Interface/Buttons/Warlords_Atlas_2.dds,2,6 + 0 + NONE + 0 + + 0 + 0 + 0 + + + 0 + 0 + 0 + + 3 + + + 0 + 0 + 0 + 0 + + + + SPECIALIST_GREAT_SPY + TXT_KEY_SPECIALIST_GREAT_SPY + TXT_KEY_CONCEPT_GREAT_SPY_PEDIA + TXT_KEY_SPECIALIST_GREAT_SPY_STRATEGY + + ,Art/Interface/Buttons/TechTree/Corporation.dds,Art/Interface/Buttons/Beyond_the_Sword_Atlas.dds,6,14 + 0 + NONE + 0 + + + 0 + 3 + 0 + 12 + + 0 + + + 0 + 0 + 0 + 0 + + + + diff --git a/Mod/RB Mod/Assets/XML/GameInfo/CIV4VoteInfo.xml b/Mod/RB Mod/Assets/XML/GameInfo/CIV4VoteInfo.xml index 66074c7..c1d7359 100644 --- a/Mod/RB Mod/Assets/XML/GameInfo/CIV4VoteInfo.xml +++ b/Mod/RB Mod/Assets/XML/GameInfo/CIV4VoteInfo.xml @@ -205,38 +205,6 @@ - - VOTE_EMANCIPATION - TXT_KEY_VOTE_EMANCIPATION - 51 - 0 - 0 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - CIVIC_EMANCIPATION - 1 - - - - - DIPLOVOTE_UN - 1 - - - VOTE_ENVIRONMENTALISM TXT_KEY_VOTE_ENVIRONMENTALISM @@ -409,221 +377,5 @@ - - VOTE_POPE - TXT_KEY_VOTE_POPE - 40 - 0 - 0 - 3 - 100 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - DIPLOVOTE_POPE - 1 - - - - - VOTE_RELIGIOUS_VICTORY - TXT_KEY_VOTE_RELIGIOUS_VICTORY - 100 - 0 - 0 - 100 - 100 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - DIPLOVOTE_POPE - 1 - - - - - VOTE_OPEN_BORDERS - TXT_KEY_VOTE_OPEN_BORDERS - 62 - 0 - 0 - 3 - 100 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - - - - DIPLOVOTE_POPE - 1 - - - - - VOTE_DEFENSIVE_PACT - TXT_KEY_VOTE_DEFENSIVE_PACT - 62 - 0 - 0 - 3 - 100 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - - - - DIPLOVOTE_POPE - 1 - - - - - VOTE_FORCE_PEACE - TXT_KEY_VOTE_FORCE_PEACE - 62 - 0 - 0 - 100 - 100 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - - - - DIPLOVOTE_POPE - 1 - - - - - VOTE_FORCE_NO_TRADE - TXT_KEY_VOTE_FORCE_NO_TRADE - 62 - 0 - 0 - 3 - 100 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - - - - DIPLOVOTE_POPE - 1 - - - - - VOTE_FORCE_WAR - TXT_KEY_VOTE_FORCE_WAR - 62 - 0 - 0 - 100 - 100 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - - - - DIPLOVOTE_POPE - 1 - - - - - VOTE_ASSIGN_CITY - TXT_KEY_VOTE_ASSIGN_CITY - 62 - 0 - 0 - 100 - 100 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - - - - DIPLOVOTE_POPE - 1 - - - \ No newline at end of file diff --git a/Mod/RB Mod/Assets/XML/GlobalDefines.xml b/Mod/RB Mod/Assets/XML/GlobalDefines.xml index 9a9ee31..646133e 100644 --- a/Mod/RB Mod/Assets/XML/GlobalDefines.xml +++ b/Mod/RB Mod/Assets/XML/GlobalDefines.xml @@ -51,7 +51,7 @@ GLOBAL_WARMING_TERRAIN - TERRAIN_DESERT + TERRAIN_PLAINS CAPITAL_BUILDINGCLASS @@ -467,11 +467,11 @@ GREAT_PEOPLE_THRESHOLD_INCREASE - 50 + 100 GREAT_PEOPLE_THRESHOLD_INCREASE_TEAM - 50 + 0 GREAT_PEOPLE_THRESHOLD @@ -479,11 +479,11 @@ GREAT_GENERALS_THRESHOLD_INCREASE - 50 + 100 GREAT_GENERALS_THRESHOLD_INCREASE_TEAM - 50 + 0 GREAT_GENERALS_THRESHOLD @@ -539,7 +539,7 @@ INITIAL_BASE_FREE_UNITS - 4 + 8 INITIAL_BASE_FREE_MILITARY_UNITS @@ -727,23 +727,23 @@ GLOBAL_WARMING_PROB - 20 + 0 GLOBAL_WARMING_FOREST - 50 + 0 GLOBAL_WARMING_UNHEALTH_WEIGHT - 20 + 0 GLOBAL_WARMING_NUKE_WEIGHT - 50 + 0 TECH_COST_EXTRA_TEAM_MEMBER_MODIFIER - 50 + 100 TECH_COST_TOTAL_KNOWN_TEAM_MODIFIER @@ -759,7 +759,7 @@ MAX_ANARCHY_TURNS - 100 + 2 MIN_REVOLUTION_TURNS @@ -1834,6 +1834,10 @@ TECH_COST_CIV_COUNT_HARD_CAP 10 + + TECH_COST_CIV_COUNT_HARD_CAP_LOWER + 10 + TECH_COST_MODIFIER_PER_ERA_MULTIPLIER 1.0 @@ -1844,11 +1848,11 @@ TECH_COST_TOTAL_MODIFIER_EARLY_CAP - 150 + 160 TECH_COST_TOTAL_MODIFIER_ADVANCED_CAP - 175 + 180 SLAVERY_NERF_ENABLED @@ -1860,7 +1864,7 @@ ENABLE_FINANCIAL_RIVERSIDE_PENALTY - 1 + 0 ENABLE_TREAT_TOROIDAL_MAINTENANCE_AS_CYLINDRICAL @@ -1882,5 +1886,24 @@ PITBOSS_PORTAL_LOG_DIRECTORY c:/temp - + + ENABLE_PITBOSS_PORTAL_GAMESTATE_LOGGING + 0 + + + ENABLE_EXTENDED_RECOVERY_SAVES + 1 + + + ENABLE_PITBOSS_PAUSE_FIX + 1 + + + TECH_COST_SCALING_ALGORITHM + 1 + + + EXTRA_SETTLED_GREAT_PEOPLE_FROM_PHI + 0 + \ No newline at end of file diff --git a/Mod/RB Mod/Assets/XML/Technologies/CIV4TechInfos.xml b/Mod/RB Mod/Assets/XML/Technologies/CIV4TechInfos.xml index 73c5213..28fdca9 100644 --- a/Mod/RB Mod/Assets/XML/Technologies/CIV4TechInfos.xml +++ b/Mod/RB Mod/Assets/XML/Technologies/CIV4TechInfos.xml @@ -16,7 +16,7 @@ ADVISOR_RELIGION 0 0 - 50 + 35 100 0 ERA_ANCIENT @@ -87,7 +87,7 @@ ADVISOR_RELIGION 0 0 - 80 + 70 100 0 ERA_ANCIENT @@ -156,7 +156,7 @@ ADVISOR_RELIGION 0 0 - 100 + 80 100 0 ERA_ANCIENT @@ -237,7 +237,7 @@ 0 0 0 - 1 + 0 0 0 0 @@ -672,7 +672,7 @@ ADVISOR_ECONOMY 0 10 - 700 + 600 100 0 ERA_MEDIEVAL @@ -890,7 +890,7 @@ ADVISOR_GROWTH 0 0 - 800 + 700 100 0 ERA_MEDIEVAL @@ -1053,7 +1053,7 @@ ADVISOR_RELIGION 0 0 - 1200 + 800 100 0 ERA_MEDIEVAL @@ -1127,7 +1127,7 @@ ADVISOR_MILITARY 0 0 - 2250 + 1600 100 0 ERA_RENAISSANCE @@ -1207,7 +1207,7 @@ ADVISOR_MILITARY 0 10 - 3000 + 2200 100 0 ERA_RENAISSANCE @@ -1278,7 +1278,7 @@ ADVISOR_ECONOMY 0 0 - 3000 + 2500 100 0 ERA_RENAISSANCE @@ -1353,7 +1353,7 @@ ADVISOR_ECONOMY 0 0 - 2100 + 1750 100 0 ERA_RENAISSANCE @@ -1424,7 +1424,7 @@ ADVISOR_ECONOMY 0 0 - 4900 + 3000 100 0 ERA_RENAISSANCE @@ -1494,7 +1494,7 @@ 2800 100 0 - ERA_RENAISSANCE + ERA_INDUSTRIAL NONE 0 0 @@ -1516,7 +1516,7 @@ 0 0 0 - 0 + 1 0 0 0 @@ -1548,6 +1548,7 @@ TECH_ECONOMICS + TECH_LIBERALISM TECH_CONSTITUTION @@ -1566,7 +1567,7 @@ ADVISOR_MILITARY 0 0 - 4800 + 2500 100 0 ERA_INDUSTRIAL @@ -1591,7 +1592,7 @@ 0 0 0 - 1 + 0 0 0 0 @@ -1627,9 +1628,10 @@ TECH_ASSEMBLY_LINE + TECH_UTOPIA - TECH_NATIONALISM + TECH_MILITARY_SCIENCE TXT_KEY_TECH_FASCISM_QUOTE AS2D_TECH_FASCISM @@ -1645,11 +1647,11 @@ ADVISOR_GROWTH 0 0 - 5600 + 3000 100 0 ERA_INDUSTRIAL - UNITCLASS_GREAT_SPY + NONE 0 0 0 @@ -1670,7 +1672,7 @@ 0 0 0 - 1 + 0 0 0 0 @@ -1720,7 +1722,7 @@ ADVISOR_CULTURE 0 0 - 7200 + 4500 100 0 ERA_MODERN @@ -1793,7 +1795,7 @@ ADVISOR_GROWTH 0 10 - 11000 + 5000 100 0 ERA_MODERN @@ -1865,7 +1867,7 @@ ADVISOR_GROWTH 0 0 - 40 + 35 100 0 ERA_ANCIENT @@ -1936,7 +1938,7 @@ ADVISOR_ECONOMY 0 0 - 60 + 35 100 0 ERA_ANCIENT @@ -2011,7 +2013,7 @@ ADVISOR_GROWTH 0 0 - 60 + 35 100 0 ERA_ANCIENT @@ -2098,7 +2100,7 @@ 0 0 0 - 1 + 0 0 0 0 @@ -2192,7 +2194,11 @@ 5 2 - + + 0 + 0 + 1 + 0 @@ -2243,7 +2249,7 @@ 0 0 0 - 1 + 0 0 0 0 @@ -2325,11 +2331,11 @@ 0 0 0 - 1 + 0 0 0 0 - 0 + 1 0 0 0 @@ -2605,7 +2611,7 @@ ADVISOR_ECONOMY 0 0 - 400 + 350 100 0 ERA_CLASSICAL @@ -2823,7 +2829,7 @@ ADVISOR_ECONOMY 0 0 - 700 + 600 100 0 ERA_MEDIEVAL @@ -2890,7 +2896,7 @@ ADVISOR_SCIENCE 0 0 - 2250 + 1600 100 0 ERA_RENAISSANCE @@ -2959,7 +2965,7 @@ ADVISOR_SCIENCE 0 0 - 2000 + 1600 100 0 ERA_RENAISSANCE @@ -3035,7 +3041,7 @@ ADVISOR_ECONOMY 0 0 - 2100 + 1750 100 0 ERA_RENAISSANCE @@ -3110,7 +3116,7 @@ ADVISOR_GROWTH 0 0 - 2500 + 1800 100 0 ERA_RENAISSANCE @@ -3186,7 +3192,7 @@ ADVISOR_MILITARY 0 0 - 2700 + 2050 100 0 ERA_RENAISSANCE @@ -3253,7 +3259,7 @@ ADVISOR_SCIENCE 0 0 - 4800 + 2700 100 0 ERA_INDUSTRIAL @@ -3325,7 +3331,7 @@ ADVISOR_SCIENCE 0 0 - 8000 + 5000 100 0 ERA_INDUSTRIAL @@ -3396,7 +3402,7 @@ ADVISOR_SCIENCE 0 0 - 7200 + 4500 100 0 ERA_INDUSTRIAL @@ -3467,7 +3473,7 @@ ADVISOR_GROWTH 0 0 - 9000 + 2100 100 0 ERA_INDUSTRIAL @@ -3546,7 +3552,7 @@ ADVISOR_ECONOMY 0 10 - 9000 + 5625 100 0 ERA_INDUSTRIAL @@ -3604,7 +3610,9 @@ TECH_PHYSICS - + + TECH_LIBERALISM + TXT_KEY_TECH_ELECTRICITY_QUOTE AS2D_TECH_ELECTRICITY AS2D_TECH_MP_ELECTRICITY @@ -3619,7 +3627,7 @@ ADVISOR_MILITARY 0 0 - 7200 + 4500 100 0 ERA_INDUSTRIAL @@ -3688,7 +3696,7 @@ ADVISOR_MILITARY 0 10 - 11000 + 6875 100 0 ERA_INDUSTRIAL @@ -3757,7 +3765,7 @@ ADVISOR_MILITARY 0 10 - 10000 + 6000 100 0 ERA_MODERN @@ -3835,7 +3843,7 @@ ADVISOR_MILITARY 0 10 - 10000 + 5500 100 0 ERA_MODERN @@ -3902,7 +3910,7 @@ ADVISOR_ECONOMY 0 0 - 14000 + 7750 100 0 ERA_MODERN @@ -3973,7 +3981,7 @@ ADVISOR_MILITARY 0 10 - 15000 + 8000 100 0 ERA_MODERN @@ -4040,7 +4048,7 @@ ADVISOR_MILITARY 0 10 - 16000 + 6000 100 0 ERA_FUTURE @@ -4107,7 +4115,7 @@ ADVISOR_GROWTH 0 10 - 14000 + 6500 100 0 ERA_FUTURE @@ -4178,7 +4186,7 @@ ADVISOR_SCIENCE 0 10 - 15000 + 8000 100 0 ERA_MODERN @@ -4244,7 +4252,7 @@ ADVISOR_SCIENCE 0 10 - 16000 + 10000 100 0 ERA_FUTURE @@ -4311,7 +4319,7 @@ ADVISOR_MILITARY 0 0 - 60 + 35 100 0 ERA_ANCIENT @@ -4386,7 +4394,7 @@ ADVISOR_ECONOMY 0 0 - 50 + 35 100 0 ERA_ANCIENT @@ -4453,7 +4461,7 @@ ADVISOR_MILITARY 0 10 - 40 + 60 100 0 ERA_ANCIENT @@ -4469,7 +4477,7 @@ 0 0 0 - 1 + 0 0 0 0 @@ -4522,7 +4530,7 @@ ADVISOR_ECONOMY 0 0 - 80 + 60 100 0 ERA_ANCIENT @@ -4538,7 +4546,7 @@ 0 0 0 - 1 + 0 0 0 0 @@ -4616,7 +4624,7 @@ 0 0 0 - 1 + 0 0 0 0 @@ -4698,7 +4706,7 @@ 0 0 0 - 1 + 0 0 0 0 @@ -4809,6 +4817,7 @@ FLAVOR_SCIENCE 1 + FLAVOR_CULTURE 5 @@ -4984,7 +4993,7 @@ ADVISOR_GROWTH 0 0 - 400 + 350 100 0 ERA_CLASSICAL @@ -5142,7 +5151,7 @@ ADVISOR_MILITARY 0 10 - 700 + 600 100 0 ERA_MEDIEVAL @@ -5365,7 +5374,7 @@ ADVISOR_MILITARY 0 10 - 1500 + 1200 100 0 ERA_RENAISSANCE @@ -5435,7 +5444,7 @@ ADVISOR_MILITARY 0 0 - 2700 + 2025 100 0 ERA_RENAISSANCE @@ -5510,7 +5519,7 @@ ADVISOR_MILITARY 0 0 - 3500 + 2000 100 0 ERA_RENAISSANCE @@ -5575,7 +5584,7 @@ ADVISOR_MILITARY 0 10 - 4200 + 3000 100 0 ERA_RENAISSANCE @@ -5646,7 +5655,7 @@ ADVISOR_ECONOMY 0 0 - 5600 + 3100 100 0 ERA_INDUSTRIAL @@ -5725,7 +5734,7 @@ ADVISOR_MILITARY 0 10 - 4900 + 3000 100 0 ERA_INDUSTRIAL @@ -5796,7 +5805,7 @@ ADVISOR_MILITARY 0 10 - 10000 + 6250 100 0 ERA_INDUSTRIAL @@ -5867,7 +5876,7 @@ ADVISOR_ECONOMY 0 10 - 9000 + 5625 100 0 ERA_INDUSTRIAL @@ -5946,7 +5955,7 @@ ADVISOR_MILITARY 0 10 - 8000 + 5000 100 0 ERA_INDUSTRIAL @@ -6014,7 +6023,7 @@ ADVISOR_ECONOMY 0 10 - 13000 + 7750 100 0 ERA_INDUSTRIAL @@ -6074,6 +6083,7 @@ TECH_ELECTRICITY + TECH_ECONOMICS TXT_KEY_TECH_INDUSTRIALISM_QUOTE AS2D_TECH_INDUSTRIALISM @@ -6089,7 +6099,7 @@ ADVISOR_CULTURE 0 0 - 12000 + 7000 100 0 ERA_MODERN @@ -6143,7 +6153,9 @@ TECH_ELECTRICITY - + + TECH_DEMOCRACY + TXT_KEY_TECH_RADIO_QUOTE AS2D_TECH_RADIO AS2D_TECH_MP_RADIO @@ -6158,7 +6170,7 @@ ADVISOR_GROWTH 0 0 - 8000 + 5000 100 0 ERA_MODERN @@ -6234,7 +6246,7 @@ ADVISOR_GROWTH 0 0 - 13000 + 7750 100 0 ERA_MODERN @@ -6300,7 +6312,7 @@ ADVISOR_SCIENCE 0 0 - 13000 + 7000 100 0 ERA_MODERN @@ -6375,7 +6387,7 @@ ADVISOR_MILITARY 0 0 - 14000 + 6500 100 0 ERA_MODERN @@ -6423,7 +6435,7 @@ - TECH_SATELLITES + TECH_ROCKETRY TECH_PLASTICS @@ -6442,7 +6454,7 @@ ADVISOR_MILITARY 0 10 - 10000 + 6500 100 0 ERA_MODERN @@ -6510,7 +6522,7 @@ ADVISOR_MILITARY 0 10 - 12000 + 7000 100 0 ERA_MODERN @@ -6581,7 +6593,7 @@ ADVISOR_SCIENCE 0 10 - 16000 + 5000 100 0 ERA_MODERN @@ -6654,7 +6666,7 @@ ADVISOR_SCIENCE 0 0 - 100000 + 10000 100 0 ERA_FUTURE diff --git a/Mod/RB Mod/Assets/XML/Terrain/CIV4BonusInfos.xml b/Mod/RB Mod/Assets/XML/Terrain/CIV4BonusInfos.xml index 6bea147..786bda5 100644 --- a/Mod/RB Mod/Assets/XML/Terrain/CIV4BonusInfos.xml +++ b/Mod/RB Mod/Assets/XML/Terrain/CIV4BonusInfos.xml @@ -14,7 +14,7 @@ TXT_KEY_BONUS_ALUMINUM_PEDIA BONUSCLASS_MODERN ART_DEF_BONUS_ALUMINUM - TECH_INDUSTRIALISM + TECH_SCIENTIFIC_METHOD TECH_MINING NONE diff --git a/Mod/RB Mod/Assets/XML/Terrain/CIV4FeatureInfos.xml b/Mod/RB Mod/Assets/XML/Terrain/CIV4FeatureInfos.xml new file mode 100644 index 0000000..681eb41 --- /dev/null +++ b/Mod/RB Mod/Assets/XML/Terrain/CIV4FeatureInfos.xml @@ -0,0 +1,686 @@ + + + + FEATURE_ICE + TXT_KEY_FEATURE_ICE + TXT_KEY_FEATURE_ICE_PEDIA + ART_DEF_FEATURE_ICE + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + + + + TERRAIN_COAST + 1 + + + TERRAIN_OCEAN + 1 + + + + + FOOTSTEP_AUDIO_HUMAN + AS3D_UN_FOOT_UNIT_SNOW + + + FOOTSTEP_AUDIO_HUMAN_LOW + AS3D_UN_FOOT_UNIT_LOW_SNOW + + + FOOTSTEP_AUDIO_ANIMAL + AS3D_UN_ANIMAL_FOOT_LARGE_SNOW + + + FOOTSTEP_AUDIO_ANIMAL_LOW + AS3D_UN_ANIMAL_FOOT_LARGE_LOW_SNOW + + + FOOTSTEP_AUDIO_HORSE + + + + LOOPSTEP_WHEELS + + + + ENDSTEP_WHEELS + + + + LOOPSTEP_WHEELS_2 + + + + ENDSTEP_WHEELS_2 + + + + LOOPSTEP_TANK + + + + ENDSTEP_TANK + + + + LOOPSTEP_MOD_ARMOUR + + + + ENDSTEP_MOD_ARMOUR + + + + LOOPSTEP_ARTILLERY + + + + ENDSTEP_ARTILLERY + + + + LOOPSTEP_WHEELS_3 + + + + ENDSTEP_WHEELS_3 + + + + NONE + 0 + 0 + + + FEATURE_JUNGLE + TXT_KEY_FEATURE_JUNGLE + TXT_KEY_FEATURE_JUNGLE_PEDIA + ART_DEF_FEATURE_JUNGLE + + -1 + 0 + 0 + + + + 2 + 1 + -25 + 50 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + TERRAIN_GRASS + 1 + + + + + FOOTSTEP_AUDIO_HUMAN + AS3D_UN_FOOT_UNIT_FOREST + + + FOOTSTEP_AUDIO_HUMAN_LOW + AS3D_UN_FOOT_UNIT_LOW_FOREST + + + FOOTSTEP_AUDIO_ANIMAL + AS3D_UN_ANIMAL_FOOT_LARGE_FOREST + + + FOOTSTEP_AUDIO_ANIMAL_LOW + AS3D_UN_ANIMAL_FOOT_LARGE_LOW_FOREST + + + FOOTSTEP_AUDIO_HORSE + AS3D_UN_HORSE_RUN_FOREST + + + LOOPSTEP_WHEELS + + + + ENDSTEP_WHEELS + + + + LOOPSTEP_WHEELS_2 + + + + ENDSTEP_WHEELS_2 + + + + LOOPSTEP_TANK + AS3D_UN_TANK_LOOP_FOREST + + + ENDSTEP_TANK + AS3D_UN_TANK_END_FOREST + + + LOOPSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_LOOP_FOREST + + + ENDSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_END_FOREST + + + LOOPSTEP_ARTILLERY + AS3D_UN_ARTILL_RUN_LOOP_FOREST + + + ENDSTEP_ARTILLERY + AS3D_UN_ARTILL_RUN_END_FOREST + + + LOOPSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_RUN_LEAVES + + + ENDSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_STOP_LEAVES + + + ASSS_JUNGLE_SELECT_AMB + EFFECT_BIRDSCATTER + 15 + 40 + + + FEATURE_OASIS + TXT_KEY_FEATURE_OASIS + TXT_KEY_FEATURE_OASIS_PEDIA + ART_DEF_FEATURE_OASIS + + 3 + 0 + 2 + + + + 2 + 1 + 0 + 0 + 500 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + 1 + 0 + 0 + + + + TERRAIN_DESERT + 1 + + + + + FOOTSTEP_AUDIO_HUMAN + AS3D_UN_FOOT_UNIT_MUD + + + FOOTSTEP_AUDIO_HUMAN_LOW + AS3D_UN_FOOT_UNIT_LOW_MUD + + + FOOTSTEP_AUDIO_ANIMAL + AS3D_UN_ANIMAL_FOOT_LARGE_MUD + + + FOOTSTEP_AUDIO_ANIMAL_LOW + AS3D_UN_ANIMAL_FOOT_LARGE_LOW_MUD + + + FOOTSTEP_AUDIO_HORSE + + + + LOOPSTEP_WHEELS + + + + ENDSTEP_WHEELS + + + + LOOPSTEP_WHEELS_2 + + + + ENDSTEP_WHEELS_2 + + + + LOOPSTEP_TANK + + + + ENDSTEP_TANK + + + + LOOPSTEP_MOD_ARMOUR + + + + ENDSTEP_MOD_ARMOUR + + + + LOOPSTEP_ARTILLERY + + + + ENDSTEP_ARTILLERY + + + + LOOPSTEP_WHEELS_3 + + + + ENDSTEP_WHEELS_3 + + + + ASSS_OASIS_SELECT_AMB + NONE + 0 + 0 + + + FEATURE_FLOOD_PLAINS + TXT_KEY_FEATURE_FLOOD_PLAINS + TXT_KEY_FEATURE_FLOOD_PLAINS_PEDIA + ART_DEF_FEATURE_FLOOD_PLAINS + + 3 + 0 + 0 + + + 0 + 0 + 1 + + + 1 + 0 + -40 + 0 + 10000 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + + + + TERRAIN_DESERT + 1 + + + + + FOOTSTEP_AUDIO_HUMAN + AS3D_UN_FOOT_UNIT_MUD + + + FOOTSTEP_AUDIO_HUMAN_LOW + AS3D_UN_FOOT_UNIT_LOW_MUD + + + FOOTSTEP_AUDIO_ANIMAL + AS3D_UN_ANIMAL_FOOT_LARGE_MUD + + + FOOTSTEP_AUDIO_ANIMAL_LOW + AS3D_UN_ANIMAL_FOOT_LARGE_LOW_MUD + + + FOOTSTEP_AUDIO_HORSE + + + + LOOPSTEP_WHEELS + + + + ENDSTEP_WHEELS + + + + LOOPSTEP_WHEELS_2 + + + + ENDSTEP_WHEELS_2 + + + + LOOPSTEP_TANK + + + + ENDSTEP_TANK + + + + LOOPSTEP_MOD_ARMOUR + + + + ENDSTEP_MOD_ARMOUR + + + + LOOPSTEP_ARTILLERY + + + + ENDSTEP_ARTILLERY + + + + LOOPSTEP_WHEELS_3 + + + + ENDSTEP_WHEELS_3 + + + + NONE + 0 + 0 + + + FEATURE_FOREST + TXT_KEY_FEATURE_FOREST + TXT_KEY_FEATURE_FOREST_PEDIA + ART_DEF_FEATURE_FOREST + + 0 + 1 + 0 + + + + 2 + 1 + 50 + 50 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + TERRAIN_GRASS + 1 + + + TERRAIN_PLAINS + 1 + + + TERRAIN_TUNDRA + 1 + + + + + FOOTSTEP_AUDIO_HUMAN + AS3D_UN_FOOT_UNIT_FOREST + + + FOOTSTEP_AUDIO_HUMAN_LOW + AS3D_UN_FOOT_UNIT_LOW_FOREST + + + FOOTSTEP_AUDIO_ANIMAL + AS3D_UN_ANIMAL_FOOT_LARGE_FOREST + + + FOOTSTEP_AUDIO_ANIMAL_LOW + AS3D_UN_ANIMAL_FOOT_LARGE_LOW_FOREST + + + FOOTSTEP_AUDIO_HORSE + AS3D_UN_HORSE_RUN_FOREST + + + LOOPSTEP_WHEELS + + + + ENDSTEP_WHEELS + + + + LOOPSTEP_WHEELS_2 + + + + ENDSTEP_WHEELS_2 + + + + LOOPSTEP_TANK + AS3D_UN_TANK_LOOP_FOREST + + + ENDSTEP_TANK + AS3D_UN_TANK_END_FOREST + + + LOOPSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_LOOP_FOREST + + + ENDSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_END_FOREST + + + LOOPSTEP_ARTILLERY + AS3D_UN_ARTILL_RUN_LOOP_FOREST + + + ENDSTEP_ARTILLERY + AS3D_UN_ARTILL_RUN_END_FOREST + + + LOOPSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_RUN_LEAVES + + + ENDSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_STOP_LEAVES + + + ASSS_FOREST_SELECT_AMB + EFFECT_BIRDSCATTER + 15 + 0 + + + FEATURE_FALLOUT + TXT_KEY_FEATURE_FALLOUT + TXT_KEY_FEATURE_FALLOUT_PEDIA + ART_DEF_FEATURE_FALLOUT + + -3 + -3 + -3 + + + + 2 + 0 + -50 + 0 + 0 + 500 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + + + + + FOOTSTEP_AUDIO_HUMAN + + + + FOOTSTEP_AUDIO_HUMAN_LOW + + + + FOOTSTEP_AUDIO_ANIMAL + + + + FOOTSTEP_AUDIO_ANIMAL_LOW + + + + FOOTSTEP_AUDIO_HORSE + + + + LOOPSTEP_WHEELS + + + + ENDSTEP_WHEELS + + + + LOOPSTEP_WHEELS_2 + + + + ENDSTEP_WHEELS_2 + + + + LOOPSTEP_TANK + + + + LOOPSTEP_MOD_ARMOUR + + + + ENDSTEP_TANK + + + + ENDSTEP_MOD_ARMOUR + + + + LOOPSTEP_ARTILLERY + + + + ENDSTEP_ARTILLERY + + + + LOOPSTEP_WHEELS_3 + + + + ENDSTEP_WHEELS_3 + + + + NONE + 0 + 0 + + + \ No newline at end of file diff --git a/Mod/RB Mod/Assets/XML/Terrain/CIV4ImprovementInfos.xml b/Mod/RB Mod/Assets/XML/Terrain/CIV4ImprovementInfos.xml index f2af492..70c28d5 100644 --- a/Mod/RB Mod/Assets/XML/Terrain/CIV4ImprovementInfos.xml +++ b/Mod/RB Mod/Assets/XML/Terrain/CIV4ImprovementInfos.xml @@ -538,7 +538,7 @@ - TECH_REPLACEABLE_PARTS + TECH_CHEMISTRY 0 1 @@ -651,6 +651,7 @@ 0 0 0 + 1 48 0 0 @@ -658,7 +659,7 @@ 0 0 5 - 0 + -50 0 5 0 @@ -671,7 +672,16 @@ - + + + TECH_CHEMISTRY + + 0 + 1 + 0 + + + ROUTE_RAILROAD @@ -787,7 +797,15 @@ 0 0 - 2 + 1 + + + + TECH_REPLACEABLE_PARTS + + 0 + 0 + 1 @@ -959,7 +977,7 @@ - TECH_REPLACEABLE_PARTS + TECH_CHEMISTRY 0 1 @@ -1407,7 +1425,7 @@ 0 0 0 - 0 + 1 1 -1 0 @@ -1422,6 +1440,52 @@ 0 + + + BONUS_ALUMINUM + 1 + 1 + 0 + + 0 + 1 + 1 + + + + BONUS_COAL + 1 + 1 + 0 + + 0 + 1 + 0 + + + + BONUS_URANIUM + 1 + 1 + 0 + + 0 + 0 + 3 + + + + BONUS_OIL + 1 + 1 + 0 + + 0 + 2 + 1 + + + IMPROVEMENT_HAMLET IMPROVEMENT_TOWN @@ -1459,7 +1523,7 @@ 0 0 0 - 0 + 1 1 -1 0 @@ -1474,6 +1538,52 @@ 0 + + + BONUS_ALUMINUM + 1 + 1 + 0 + + 0 + 1 + 1 + + + + BONUS_COAL + 1 + 1 + 0 + + 0 + 1 + 0 + + + + BONUS_URANIUM + 1 + 1 + 0 + + 0 + 0 + 3 + + + + BONUS_OIL + 1 + 1 + 0 + + 0 + 2 + 1 + + + IMPROVEMENT_VILLAGE @@ -1603,4 +1713,4 @@ 0 - \ No newline at end of file + diff --git a/Mod/RB Mod/Assets/XML/Terrain/CIV4TerrainInfos.xml b/Mod/RB Mod/Assets/XML/Terrain/CIV4TerrainInfos.xml new file mode 100644 index 0000000..05a3094 --- /dev/null +++ b/Mod/RB Mod/Assets/XML/Terrain/CIV4TerrainInfos.xml @@ -0,0 +1,1376 @@ + + + + + + + + + + TERRAIN_GRASS + TXT_KEY_TERRAIN_GRASS + TXT_KEY_TERRAIN_GRASS_PEDIA + ART_DEF_TERRAIN_GRASS + + 2 + 0 + 0 + + + 0 + 0 + 1 + + + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 0 + 0 + + + + FOOTSTEP_AUDIO_HUMAN + AS3D_UN_FOOT_UNIT + + + FOOTSTEP_AUDIO_HUMAN_LOW + AS3D_UN_FOOT_UNIT_LOW + + + FOOTSTEP_AUDIO_ANIMAL + AS3D_UN_ANIMAL_FOOT_LARGE + + + FOOTSTEP_AUDIO_ANIMAL_LOW + AS3D_UN_ANIMAL_FOOT_LARGE_LOW + + + FOOTSTEP_AUDIO_HORSE + AS3D_UN_HORSE_RUN + + + LOOPSTEP_WHEELS + AS3D_UN_CHARIOT_LOOP + + + ENDSTEP_WHEELS + AS3D_UN_CHARIOT_END + + + LOOPSTEP_WHEELS_2 + AS3D_UN_WAR_CHARIOT_LOOP + + + ENDSTEP_WHEELS_2 + AS3D_UN_WAR_CHARIOT_END + + + LOOPSTEP_TANK + AS3D_UN_TANK_LOOP + + + ENDSTEP_TANK + AS3D_UN_TANK_END + + + LOOPSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_LOOP + + + ENDSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_END + + + LOOPSTEP_OCEAN1 + AS3D_UN_OCEAN_LOOP1 + + + ENDSTEP_OCEAN1 + AS3D_UN_OCEAN_END1 + + + LOOPSTEP_OCEAN2 + AS3D_UN_OCEAN_LOOP1 + + + ENDSTEP_OCEAN2 + AS3D_UN_OCEAN_END2 + + + LOOPSTEP_DESTOYER + AS3D_UN_DESTROYER_RUN_LOOP + + + ENDSTEP_DESTROYER + AS3D_UN_DESTROYER_RUN_END + + + LOOPSTEP_IRONCLAD + AS3D_UN_IRONCLAD_RUN_LOOP + + + ENDSTEP_IRONCLAD + AS3D_UN_IRONCLAD_RUN_END + + + LOOPSTEP_TRANSPORT + AS3D_UN_TRANSPORT_RUN_LOOP + + + ENDSTEP_TRANSPORT + AS3D_UN_TRANSPORT_RUN_END + + + LOOPSTEP_SUBMARINE + AS3D_UN_SUBMARINE_RUN_LOOP + + + ENDSTEP_SUBMARINE + AS3D_UN_SUBMARINE_RUN_END + + + LOOPSTEP_GUNSHIP + AS3D_UN_GUNSHIP_RUN_LOOP + + + ENDSTEP_GUNSHIP + AS3D_UN_GUNSHIP_RUN_END + + + LOOPSTEP_ARTILLERY + AS3D_UN_ARTILLERY_RUN_LOOP + + + ENDSTEP_ARTILLERY + AS3D_UN_ARTILLERY_RUN_END + + + LOOPSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_RUN + + + ENDSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_STOP + + + ASSS_GRASSLAND_SELECT_AMB + 0 + + + TERRAIN_PLAINS + TXT_KEY_TERRAIN_PLAINS + TXT_KEY_TERRAIN_PLAINS_PEDIA + ART_DEF_TERRAIN_PLAINS + + 1 + 1 + 0 + + + 0 + 0 + 1 + + + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 0 + 0 + + + + FOOTSTEP_AUDIO_HUMAN + AS3D_UN_FOOT_UNIT + + + FOOTSTEP_AUDIO_HUMAN_LOW + AS3D_UN_FOOT_UNIT_LOW + + + FOOTSTEP_AUDIO_ANIMAL + AS3D_UN_ANIMAL_FOOT_LARGE + + + FOOTSTEP_AUDIO_ANIMAL_LOW + AS3D_UN_ANIMAL_FOOT_LARGE_LOW + + + FOOTSTEP_AUDIO_HORSE + AS3D_UN_HORSE_RUN + + + LOOPSTEP_WHEELS + AS3D_UN_CHARIOT_LOOP + + + ENDSTEP_WHEELS + AS3D_UN_CHARIOT_END + + + LOOPSTEP_WHEELS_2 + AS3D_UN_WAR_CHARIOT_LOOP + + + ENDSTEP_WHEELS_2 + AS3D_UN_WAR_CHARIOT_END + + + LOOPSTEP_TANK + AS3D_UN_TANK_LOOP + + + ENDSTEP_TANK + AS3D_UN_TANK_END + + + LOOPSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_LOOP + + + ENDSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_END + + + LOOPSTEP_OCEAN1 + AS3D_UN_OCEAN_LOOP1 + + + ENDSTEP_OCEAN1 + AS3D_UN_OCEAN_END1 + + + LOOPSTEP_OCEAN2 + AS3D_UN_OCEAN_LOOP1 + + + ENDSTEP_OCEAN2 + AS3D_UN_OCEAN_END2 + + + LOOPSTEP_DESTOYER + AS3D_UN_DESTROYER_RUN_LOOP + + + ENDSTEP_DESTROYER + AS3D_UN_DESTROYER_RUN_END + + + LOOPSTEP_IRONCLAD + AS3D_UN_IRONCLAD_RUN_LOOP + + + ENDSTEP_IRONCLAD + AS3D_UN_IRONCLAD_RUN_END + + + LOOPSTEP_TRANSPORT + AS3D_UN_TRANSPORT_RUN_LOOP + + + ENDSTEP_TRANSPORT + AS3D_UN_TRANSPORT_RUN_END + + + LOOPSTEP_SUBMARINE + AS3D_UN_SUBMARINE_RUN_LOOP + + + ENDSTEP_SUBMARINE + AS3D_UN_SUBMARINE_RUN_END + + + LOOPSTEP_GUNSHIP + AS3D_UN_GUNSHIP_RUN_LOOP + + + ENDSTEP_GUNSHIP + AS3D_UN_GUNSHIP_RUN_END + + + LOOPSTEP_ARTILLERY + AS3D_UN_ARTILLERY_RUN_LOOP + + + ENDSTEP_ARTILLERY + AS3D_UN_ARTILLERY_RUN_END + + + LOOPSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_RUN + + + ENDSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_STOP + + + ASSS_PLAINS_SELECT_AMB + 0 + + + TERRAIN_DESERT + TXT_KEY_TERRAIN_DESERT + TXT_KEY_TERRAIN_DESERT_PEDIA + ART_DEF_TERRAIN_DESERT + + + 0 + 0 + 1 + + + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 25 + 0 + + + + FOOTSTEP_AUDIO_HUMAN + AS3D_UN_FOOT_UNIT_SAND + + + FOOTSTEP_AUDIO_HUMAN_LOW + AS3D_UN_FOOT_UNIT_LOW_SAND + + + FOOTSTEP_AUDIO_ANIMAL + AS3D_UN_ANIMAL_FOOT_LARGE_SAND + + + FOOTSTEP_AUDIO_ANIMAL_LOW + AS3D_UN_ANIMAL_FOOT_LARGE_LOW_SAND + + + FOOTSTEP_AUDIO_HORSE + AS3D_UN_HORSE_RUN + + + LOOPSTEP_WHEELS + AS3D_UN_CHARIOT_LOOP + + + ENDSTEP_WHEELS + AS3D_UN_CHARIOT_END + + + LOOPSTEP_WHEELS_2 + AS3D_UN_WAR_CHARIOT_LOOP + + + ENDSTEP_WHEELS_2 + AS3D_UN_WAR_CHARIOT_END + + + LOOPSTEP_TANK + AS3D_UN_TANK_LOOP + + + ENDSTEP_TANK + AS3D_UN_TANK_END + + + LOOPSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_LOOP + + + ENDSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_END + + + LOOPSTEP_OCEAN1 + AS3D_UN_OCEAN_LOOP1 + + + ENDSTEP_OCEAN1 + AS3D_UN_OCEAN_END1 + + + LOOPSTEP_OCEAN2 + AS3D_UN_OCEAN_LOOP1 + + + ENDSTEP_OCEAN2 + AS3D_UN_OCEAN_END2 + + + LOOPSTEP_DESTOYER + AS3D_UN_DESTROYER_RUN_LOOP + + + ENDSTEP_DESTROYER + AS3D_UN_DESTROYER_RUN_END + + + LOOPSTEP_IRONCLAD + AS3D_UN_IRONCLAD_RUN_LOOP + + + ENDSTEP_IRONCLAD + AS3D_UN_IRONCLAD_RUN_END + + + LOOPSTEP_TRANSPORT + AS3D_UN_TRANSPORT_RUN_LOOP + + + ENDSTEP_TRANSPORT + AS3D_UN_TRANSPORT_RUN_END + + + LOOPSTEP_SUBMARINE + AS3D_UN_SUBMARINE_RUN_LOOP + + + ENDSTEP_SUBMARINE + AS3D_UN_SUBMARINE_RUN_END + + + LOOPSTEP_GUNSHIP + AS3D_UN_GUNSHIP_RUN_LOOP + + + ENDSTEP_GUNSHIP + AS3D_UN_GUNSHIP_RUN_END + + + LOOPSTEP_ARTILLERY + AS3D_UN_ARTILLERY_RUN_LOOP + + + ENDSTEP_ARTILLERY + AS3D_UN_ARTILLERY_RUN_END + + + LOOPSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_RUN + + + ENDSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_STOP + + + ASSS_DESERT_SELECT_AMB + 0 + + + TERRAIN_TUNDRA + TXT_KEY_TERRAIN_TUNDRA + TXT_KEY_TERRAIN_TUNDRA_PEDIA + ART_DEF_TERRAIN_TUNDRA + + 1 + 0 + 0 + + + 0 + 0 + 1 + + + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 25 + 0 + + + + FOOTSTEP_AUDIO_HUMAN + AS3D_UN_FOOT_UNIT_TUNDRA + + + FOOTSTEP_AUDIO_HUMAN_LOW + AS3D_UN_FOOT_UNIT_LOW_TUNDRA + + + FOOTSTEP_AUDIO_ANIMAL + AS3D_UN_ANIMAL_FOOT_LARGE_TUNDRA + + + FOOTSTEP_AUDIO_ANIMAL_LOW + AS3D_UN_ANIMAL_FOOT_LARGE_LOW_TUNDRA + + + FOOTSTEP_AUDIO_HORSE + AS3D_UN_HORSE_RUN + + + LOOPSTEP_WHEELS + AS3D_UN_CHARIOT_LOOP + + + ENDSTEP_WHEELS + AS3D_UN_CHARIOT_END + + + LOOPSTEP_WHEELS_2 + AS3D_UN_WAR_CHARIOT_LOOP + + + ENDSTEP_WHEELS_2 + AS3D_UN_WAR_CHARIOT_END + + + LOOPSTEP_TANK + AS3D_UN_TANK_LOOP + + + ENDSTEP_TANK + AS3D_UN_TANK_END + + + LOOPSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_LOOP + + + ENDSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_END + + + LOOPSTEP_OCEAN1 + AS3D_UN_OCEAN_LOOP1 + + + ENDSTEP_OCEAN1 + AS3D_UN_OCEAN_END1 + + + LOOPSTEP_OCEAN2 + AS3D_UN_OCEAN_LOOP1 + + + ENDSTEP_OCEAN2 + AS3D_UN_OCEAN_END2 + + + LOOPSTEP_DESTOYER + AS3D_UN_DESTROYER_RUN_LOOP + + + ENDSTEP_DESTROYER + AS3D_UN_DESTROYER_RUN_END + + + LOOPSTEP_IRONCLAD + AS3D_UN_IRONCLAD_RUN_LOOP + + + ENDSTEP_IRONCLAD + AS3D_UN_IRONCLAD_RUN_END + + + LOOPSTEP_TRANSPORT + AS3D_UN_TRANSPORT_RUN_LOOP + + + ENDSTEP_TRANSPORT + AS3D_UN_TRANSPORT_RUN_END + + + LOOPSTEP_SUBMARINE + AS3D_UN_SUBMARINE_RUN_LOOP + + + ENDSTEP_SUBMARINE + AS3D_UN_SUBMARINE_RUN_END + + + LOOPSTEP_GUNSHIP + AS3D_UN_GUNSHIP_RUN_LOOP + + + ENDSTEP_GUNSHIP + AS3D_UN_GUNSHIP_RUN_END + + + LOOPSTEP_ARTILLERY + AS3D_UN_ARTILLERY_RUN_LOOP + + + ENDSTEP_ARTILLERY + AS3D_UN_ARTILLERY_RUN_END + + + LOOPSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_RUN + + + ENDSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_STOP + + + ASSS_TUNDRA_SELECT_AMB + 0 + + + TERRAIN_SNOW + TXT_KEY_TERRAIN_ICE + TXT_KEY_TERRAIN_ICE_PEDIA + ART_DEF_TERRAIN_SNOW + + + + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 50 + 0 + + + + FOOTSTEP_AUDIO_HUMAN + AS3D_UN_FOOT_UNIT_SNOW + + + FOOTSTEP_AUDIO_HUMAN_LOW + AS3D_UN_FOOT_UNIT_LOW_SNOW + + + FOOTSTEP_AUDIO_ANIMAL + AS3D_UN_ANIMAL_FOOT_LARGE_SNOW + + + FOOTSTEP_AUDIO_ANIMAL_LOW + AS3D_UN_ANIMAL_FOOT_LARGE_LOW_SNOW + + + FOOTSTEP_AUDIO_HORSE + AS3D_UN_HORSE_RUN + + + LOOPSTEP_WHEELS + AS3D_UN_CHARIOT_LOOP + + + ENDSTEP_WHEELS + AS3D_UN_CHARIOT_END + + + LOOPSTEP_WHEELS_2 + AS3D_UN_WAR_CHARIOT_LOOP + + + ENDSTEP_WHEELS_2 + AS3D_UN_WAR_CHARIOT_END + + + LOOPSTEP_TANK + AS3D_UN_TANK_LOOP + + + ENDSTEP_TANK + AS3D_UN_TANK_END + + + LOOPSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_LOOP + + + ENDSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_END + + + LOOPSTEP_OCEAN1 + AS3D_UN_OCEAN_LOOP1 + + + ENDSTEP_OCEAN1 + AS3D_UN_OCEAN_END1 + + + LOOPSTEP_OCEAN2 + AS3D_UN_OCEAN_LOOP1 + + + ENDSTEP_OCEAN2 + AS3D_UN_OCEAN_END2 + + + LOOPSTEP_DESTOYER + AS3D_UN_DESTROYER_RUN_LOOP + + + ENDSTEP_DESTROYER + AS3D_UN_DESTROYER_RUN_END + + + LOOPSTEP_IRONCLAD + AS3D_UN_IRONCLAD_RUN_LOOP + + + ENDSTEP_IRONCLAD + AS3D_UN_IRONCLAD_RUN_END + + + LOOPSTEP_TRANSPORT + AS3D_UN_TRANSPORT_RUN_LOOP + + + ENDSTEP_TRANSPORT + AS3D_UN_TRANSPORT_RUN_END + + + LOOPSTEP_SUBMARINE + AS3D_UN_SUBMARINE_RUN_LOOP + + + ENDSTEP_SUBMARINE + AS3D_UN_SUBMARINE_RUN_END + + + LOOPSTEP_GUNSHIP + AS3D_UN_GUNSHIP_RUN_LOOP + + + ENDSTEP_GUNSHIP + AS3D_UN_GUNSHIP_RUN_END + + + LOOPSTEP_ARTILLERY + AS3D_UN_ARTILLERY_RUN_LOOP + + + ENDSTEP_ARTILLERY + AS3D_UN_ARTILLERY_RUN_END + + + LOOPSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_RUN + + + ENDSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_STOP + + + ASSS_TUNDRA_SELECT_AMB + 0 + + + TERRAIN_COAST + TXT_KEY_TERRAIN_COAST + TXT_KEY_TERRAIN_COAST_PEDIA + ART_DEF_TERRAIN_COAST + + 1 + 0 + 2 + + + + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 10 + + + + FOOTSTEP_AUDIO_HUMAN + AS3D_UN_FOOT_UNIT_SAND + + + FOOTSTEP_AUDIO_HUMAN_LOW + AS3D_UN_FOOT_UNIT_LOW_SAND + + + FOOTSTEP_AUDIO_ANIMAL + AS3D_UN_ANIMAL_FOOT_LARGE_SAND + + + FOOTSTEP_AUDIO_ANIMAL_LOW + AS3D_UN_ANIMAL_FOOT_LARGE_LOW_SAND + + + FOOTSTEP_AUDIO_HORSE + AS3D_UN_HORSE_RUN + + + LOOPSTEP_WHEELS + AS3D_UN_CHARIOT_LOOP + + + ENDSTEP_WHEELS + AS3D_UN_CHARIOT_END + + + LOOPSTEP_WHEELS_2 + AS3D_UN_WAR_CHARIOT_LOOP + + + ENDSTEP_WHEELS_2 + AS3D_UN_WAR_CHARIOT_END + + + LOOPSTEP_TANK + AS3D_UN_TANK_LOOP + + + ENDSTEP_TANK + AS3D_UN_TANK_END + + + LOOPSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_LOOP + + + ENDSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_END + + + LOOPSTEP_OCEAN1 + AS3D_UN_OCEAN_LOOP1 + + + ENDSTEP_OCEAN1 + AS3D_UN_OCEAN_END1 + + + LOOPSTEP_OCEAN2 + AS3D_UN_OCEAN_LOOP1 + + + ENDSTEP_OCEAN2 + AS3D_UN_OCEAN_END2 + + + LOOPSTEP_DESTOYER + AS3D_UN_DESTROYER_RUN_LOOP + + + ENDSTEP_DESTROYER + AS3D_UN_DESTROYER_RUN_END + + + LOOPSTEP_IRONCLAD + AS3D_UN_IRONCLAD_RUN_LOOP + + + ENDSTEP_IRONCLAD + AS3D_UN_IRONCLAD_RUN_END + + + LOOPSTEP_TRANSPORT + AS3D_UN_TRANSPORT_RUN_LOOP + + + ENDSTEP_TRANSPORT + AS3D_UN_TRANSPORT_RUN_END + + + LOOPSTEP_SUBMARINE + AS3D_UN_SUBMARINE_RUN_LOOP + + + ENDSTEP_SUBMARINE + AS3D_UN_SUBMARINE_RUN_END + + + LOOPSTEP_GUNSHIP + AS3D_UN_GUNSHIP_RUN_LOOP + + + ENDSTEP_GUNSHIP + AS3D_UN_GUNSHIP_RUN_END + + + LOOPSTEP_ARTILLERY + AS3D_UN_ARTILLERY_RUN_LOOP + + + ENDSTEP_ARTILLERY + AS3D_UN_ARTILLERY_RUN_END + + + LOOPSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_RUN + + + ENDSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_STOP + + + ASSS_COAST_SELECT_AMB + 0 + + + TERRAIN_OCEAN + TXT_KEY_TERRAIN_OCEAN + TXT_KEY_TERRAIN_OCEAN_PEDIA + ART_DEF_TERRAIN_OCEAN + + 1 + 0 + 1 + + + + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + + + + FOOTSTEP_AUDIO_HUMAN + AS3D_UN_FOOT_UNIT_MUD + + + FOOTSTEP_AUDIO_HUMAN_LOW + AS3D_UN_FOOT_UNIT_LOW_MUD + + + FOOTSTEP_AUDIO_ANIMAL + AS3D_UN_ANIMAL_FOOT_LARGE_MUD + + + FOOTSTEP_AUDIO_ANIMAL_LOW + AS3D_UN_ANIMAL_FOOT_LARGE_LOW_MUD + + + FOOTSTEP_AUDIO_HORSE + AS3D_UN_HORSE_RUN + + + LOOPSTEP_WHEELS + AS3D_UN_CHARIOT_LOOP + + + ENDSTEP_WHEELS + AS3D_UN_CHARIOT_END + + + LOOPSTEP_WHEELS_2 + AS3D_UN_WAR_CHARIOT_LOOP + + + ENDSTEP_WHEELS_2 + AS3D_UN_WAR_CHARIOT_END + + + LOOPSTEP_TANK + AS3D_UN_TANK_LOOP + + + ENDSTEP_TANK + AS3D_UN_TANK_END + + + LOOPSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_LOOP + + + ENDSTEP_MOD_ARMOUR + AS3D_UN_MOD_ARMOUR_END + + + LOOPSTEP_OCEAN1 + AS3D_UN_OCEAN_LOOP1 + + + ENDSTEP_OCEAN1 + AS3D_UN_OCEAN_END1 + + + LOOPSTEP_OCEAN2 + AS3D_UN_OCEAN_LOOP1 + + + ENDSTEP_OCEAN2 + AS3D_UN_OCEAN_END2 + + + LOOPSTEP_DESTOYER + AS3D_UN_DESTROYER_RUN_LOOP + + + ENDSTEP_DESTROYER + AS3D_UN_DESTROYER_RUN_END + + + LOOPSTEP_IRONCLAD + AS3D_UN_IRONCLAD_RUN_LOOP + + + ENDSTEP_IRONCLAD + AS3D_UN_IRONCLAD_RUN_END + + + LOOPSTEP_TRANSPORT + AS3D_UN_TRANSPORT_RUN_LOOP + + + ENDSTEP_TRANSPORT + AS3D_UN_TRANSPORT_RUN_END + + + LOOPSTEP_SUBMARINE + AS3D_UN_SUBMARINE_RUN_LOOP + + + ENDSTEP_SUBMARINE + AS3D_UN_SUBMARINE_RUN_END + + + LOOPSTEP_GUNSHIP + AS3D_UN_GUNSHIP_RUN_LOOP + + + ENDSTEP_GUNSHIP + AS3D_UN_GUNSHIP_RUN_END + + + LOOPSTEP_ARTILLERY + AS3D_UN_ARTILLERY_RUN_LOOP + + + ENDSTEP_ARTILLERY + AS3D_UN_ARTILLERY_RUN_END + + + LOOPSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_RUN + + + ENDSTEP_WHEELS_3 + AS3D_UN_TREBUCHET_STOP + + + ASSS_OCEAN_SELECT_AMB + 0 + + + TERRAIN_PEAK + TXT_KEY_TERRAIN_PEAK + TXT_KEY_TERRAIN_PEAK_PEDIA + ART_DEF_TERRAIN_PEAK + + + + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + + + + FOOTSTEP_AUDIO_HUMAN + + + + FOOTSTEP_AUDIO_HUMAN_LOW + + + + FOOTSTEP_AUDIO_ANIMAL + + + + FOOTSTEP_AUDIO_ANIMAL_LOW + + + + FOOTSTEP_AUDIO_HORSE + + + + LOOPSTEP_WHEELS + + + + ENDSTEP_WHEELS + + + + LOOPSTEP_WHEELS_2 + + + + ENDSTEP_WHEELS_2 + + + + LOOPSTEP_TANK + + + + ENDSTEP_TANK + + + + LOOPSTEP_MOD_ARMOUR + + + + ENDSTEP_MOD_ARMOUR + + + + LOOPSTEP_OCEAN1 + + + + ENDSTEP_OCEAN1 + + + + LOOPSTEP_OCEAN2 + + + + ENDSTEP_OCEAN2 + + + + LOOPSTEP_DESTOYER + + + + ENDSTEP_DESTROYER + + + + LOOPSTEP_IRONCLAD + + + + ENDSTEP_IRONCLAD + + + + LOOPSTEP_TRANSPORT + + + + ENDSTEP_TRANSPORT + + + + LOOPSTEP_SUBMARINE + + + + ENDSTEP_SUBMARINE + + + + LOOPSTEP_GUNSHIP + + + + ENDSTEP_GUNSHIP + + + + LOOPSTEP_ARTILLERY + + + + ENDSTEP_ARTILLERY + + + + LOOPSTEP_WHEELS_3 + + + + ENDSTEP_WHEELS_3 + + + + 1 + + + TERRAIN_HILL + TXT_KEY_TERRAIN_HILL + TXT_KEY_TERRAIN_HILL_PEDIA + ART_DEF_TERRAIN_HILL + + + + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + + + + FOOTSTEP_AUDIO_HUMAN + + + + FOOTSTEP_AUDIO_HUMAN_LOW + + + + FOOTSTEP_AUDIO_ANIMAL + + + + FOOTSTEP_AUDIO_ANIMAL_LOW + + + + FOOTSTEP_AUDIO_HORSE + + + + LOOPSTEP_WHEELS + + + + ENDSTEP_WHEELS + + + + LOOPSTEP_WHEELS_2 + + + + ENDSTEP_WHEELS_2 + + + + LOOPSTEP_TANK + + + + ENDSTEP_TANK + + + + LOOPSTEP_MOD_ARMOUR + + + + ENDSTEP_MOD_ARMOUR + + + + LOOPSTEP_OCEAN1 + + + + ENDSTEP_OCEAN1 + + + + LOOPSTEP_OCEAN2 + + + + ENDSTEP_OCEAN2 + + + + LOOPSTEP_DESTOYER + + + + ENDSTEP_DESTROYER + + + + LOOPSTEP_IRONCLAD + + + + ENDSTEP_IRONCLAD + + + + LOOPSTEP_TRANSPORT + + + + ENDSTEP_TRANSPORT + + + + LOOPSTEP_SUBMARINE + + + + ENDSTEP_SUBMARINE + + + + LOOPSTEP_GUNSHIP + + + + ENDSTEP_GUNSHIP + + + + LOOPSTEP_ARTILLERY + + + + ENDSTEP_ARTILLERY + + + + LOOPSTEP_WHEELS_3 + + + + ENDSTEP_WHEELS_3 + + + + 1 + + + diff --git a/Mod/RB Mod/Assets/XML/Terrain/CIV4TerrainSchema.xml b/Mod/RB Mod/Assets/XML/Terrain/CIV4TerrainSchema.xml new file mode 100644 index 0000000..69e2af8 --- /dev/null +++ b/Mod/RB Mod/Assets/XML/Terrain/CIV4TerrainSchema.xml @@ -0,0 +1,502 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mod/RB Mod/Assets/XML/Terrain/CIV4YieldInfos.xml b/Mod/RB Mod/Assets/XML/Terrain/CIV4YieldInfos.xml index 02cec7a..043058a 100644 --- a/Mod/RB Mod/Assets/XML/Terrain/CIV4YieldInfos.xml +++ b/Mod/RB Mod/Assets/XML/Terrain/CIV4YieldInfos.xml @@ -13,9 +13,11 @@ 0 1 0 + 0 0 0 2 + 2 0 0 0 @@ -36,9 +38,11 @@ 0 0 0 + 0 0 0 1 + 2 0 1 1 @@ -59,9 +63,11 @@ 0 0 0 + 0 0 0 1 + 1 100 1 1 diff --git a/Mod/RB Mod/Assets/XML/Text/CIV4GameText_BTS_Fixed.xml b/Mod/RB Mod/Assets/XML/Text/CIV4GameText_BTS_Fixed.xml index 35d1068..c0a9f7d 100644 --- a/Mod/RB Mod/Assets/XML/Text/CIV4GameText_BTS_Fixed.xml +++ b/Mod/RB Mod/Assets/XML/Text/CIV4GameText_BTS_Fixed.xml @@ -433,4 +433,13 @@ Il [COLOR_BUILDING_TEXT]dun[COLOR_REVERT], l'equivalente celtico delle [COLOR_BUILDING_TEXT]mura[COLOR_REVERT], potenzia le difese della città contro le unità precedenti alla polvere da sparo e garantisce a tutte le unità adatte costruite in città la promozione [COLOR_HIGHLIGHT_TEXT]Guerriglia II[COLOR_REVERT]. Los [COLOR_BUILDING_TEXT]Duns[COLOR_REVERT], los equivalentes celtas de las [COLOR_BUILDING_TEXT]Murallas[COLOR_REVERT], aumentan las defensas de una ciudad contra unidades anteriores a las armas de pólvora y otorgan a todas las unidades pertinentes que se construyan en esa ciudad el ascenso a [COLOR_HIGHLIGHT_TEXT]Guerra de guerrillas II[COLOR_REVERT]. + + TXT_KEY_TRAIT_CITY_UPKEEP_MODIFIER + [ICON_BULLET]-25% city maintenance + [ICON_BULLET]-25% city maintenance + [ICON_BULLET]-25% city maintenance + [ICON_BULLET]-25% city maintenance + [ICON_BULLET]-25% city maintenance + + diff --git a/Mod/RB Mod/Assets/XML/Text/RtR_Civ4GameText.xml b/Mod/RB Mod/Assets/XML/Text/RtR_Civ4GameText.xml new file mode 100644 index 0000000..8093929 --- /dev/null +++ b/Mod/RB Mod/Assets/XML/Text/RtR_Civ4GameText.xml @@ -0,0 +1,23 @@ + + + + + + + + TXT_KEY_GAME_OPTION_NO_CITY_TRADING + No city trading + No city trading + No city trading + No city trading + No city trading + + + TXT_KEY_GAME_OPTION_NO_CITY_TRADING_HELP + City trading is disabled from the diplo window. + City trading is disabled from the diplo window. + City trading is disabled from the diplo window. + City trading is disabled from the diplo window. + City trading is disabled from the diplo window. + + \ No newline at end of file diff --git a/Mod/RB Mod/Assets/XML/Units/CIV4BuildInfos.xml b/Mod/RB Mod/Assets/XML/Units/CIV4BuildInfos.xml index 100490c..97c3973 100644 --- a/Mod/RB Mod/Assets/XML/Units/CIV4BuildInfos.xml +++ b/Mod/RB Mod/Assets/XML/Units/CIV4BuildInfos.xml @@ -188,8 +188,8 @@ BUILD_LUMBERMILL TXT_KEY_BUILD_LUMBERMILL - TECH_REPLACEABLE_PARTS - 800 + TECH_METAL_CASTING + 500 0 0 IMPROVEMENT_LUMBERMILL @@ -431,9 +431,9 @@ TXT_KEY_BUILD_OFFSHORE_PLATFORM TECH_PLASTICS - 0 + 100 0 - 1 + 0 IMPROVEMENT_OFFSHORE_PLATFORM NONE ENTITY_EVENT_BUILD @@ -617,7 +617,7 @@ BUILD_FOREST_PRESERVE TXT_KEY_BUILD_FOREST_PRESERVE - TECH_SCIENTIFIC_METHOD + TECH_REPLACEABLE_PARTS 800 0 0 @@ -633,4 +633,4 @@ - \ No newline at end of file + diff --git a/Mod/RB Mod/Assets/XML/Units/CIV4PromotionInfos.xml b/Mod/RB Mod/Assets/XML/Units/CIV4PromotionInfos.xml index 456bf4b..e2bb118 100644 --- a/Mod/RB Mod/Assets/XML/Units/CIV4PromotionInfos.xml +++ b/Mod/RB Mod/Assets/XML/Units/CIV4PromotionInfos.xml @@ -844,7 +844,7 @@ NONE NONE PROMOTION_COMBAT1 - NONE + PROMOTION_DRILL1 NONE NONE 0 @@ -1016,7 +1016,7 @@ NONE NONE PROMOTION_COMBAT2 - NONE + PROMOTION_DRILL2 NONE NONE 0 @@ -1099,7 +1099,7 @@ NONE NONE PROMOTION_COMBAT3 - PROMOTION_MEDIC1 + PROMOTION_DRILL3 NONE NONE 0 @@ -1186,7 +1186,7 @@ NONE NONE PROMOTION_COMBAT3 - NONE + PROMOTION_DRILL3 TECH_MILITARY_SCIENCE NONE 0 @@ -1265,7 +1265,7 @@ NONE NONE PROMOTION_COMBAT4 - NONE + PROMOTION_DRILL4 TECH_MILITARY_SCIENCE NONE 0 @@ -3951,6 +3951,7 @@ 0 0 0 + 0 25 0 @@ -4550,4 +4551,4 @@ - \ No newline at end of file + diff --git a/Mod/RB Mod/Assets/XML/Units/CIV4UnitClassInfos.xml b/Mod/RB Mod/Assets/XML/Units/CIV4UnitClassInfos.xml new file mode 100644 index 0000000..b89ef8f --- /dev/null +++ b/Mod/RB Mod/Assets/XML/Units/CIV4UnitClassInfos.xml @@ -0,0 +1,820 @@ + + + + + + + + + + UNITCLASS_LION + TXT_KEY_UNIT_LION + -1 + -1 + -1 + 0 + UNIT_LION + + + UNITCLASS_BEAR + TXT_KEY_UNIT_BEAR + -1 + -1 + -1 + 0 + UNIT_BEAR + + + UNITCLASS_PANTHER + TXT_KEY_UNIT_PANTHER + -1 + -1 + -1 + 0 + UNIT_PANTHER + + + UNITCLASS_WOLF + TXT_KEY_UNIT_WOLF + -1 + -1 + -1 + 0 + UNIT_WOLF + + + UNITCLASS_SETTLER + TXT_KEY_UNIT_SETTLER + -1 + -1 + -1 + 0 + UNIT_SETTLER + + + UNITCLASS_WORKER + TXT_KEY_UNIT_WORKER + -1 + -1 + -1 + 0 + UNIT_WORKER + + + UNITCLASS_FAST_WORKER + TXT_KEY_UNIT_WORKER + -1 + -1 + -1 + 0 + UNIT_FAST_WORKER + + + UNITCLASS_SCOUT + TXT_KEY_UNIT_SCOUT + -1 + -1 + -1 + 0 + UNIT_SCOUT + + + UNITCLASS_EXPLORER + TXT_KEY_UNIT_EXPLORER + -1 + -1 + -1 + 0 + UNIT_EXPLORER + + + UNITCLASS_SPY + TXT_KEY_UNIT_SPY + -1 + -1 + -1 + 0 + UNIT_SPY + + + UNITCLASS_EXECUTIVE_1 + TXT_KEY_UNIT_EXECUTIVE_1 + -1 + -1 + 5 + 0 + UNIT_EXECUTIVE_1 + + + UNITCLASS_EXECUTIVE_2 + CHANGED_TXT_KEY_UNIT_EXECUTIVE_2 + -1 + -1 + 5 + 0 + UNIT_EXECUTIVE_2 + + + UNITCLASS_EXECUTIVE_3 + TXT_KEY_UNIT_EXECUTIVE_3 + -1 + -1 + 5 + 0 + UNIT_EXECUTIVE_3 + + + UNITCLASS_EXECUTIVE_4 + TXT_KEY_UNIT_EXECUTIVE_4 + -1 + -1 + 5 + 0 + UNIT_EXECUTIVE_4 + + + UNITCLASS_EXECUTIVE_5 + TXT_KEY_UNIT_EXECUTIVE_5 + -1 + -1 + 5 + 0 + UNIT_EXECUTIVE_5 + + + UNITCLASS_EXECUTIVE_6 + TXT_KEY_UNIT_EXECUTIVE_6 + -1 + -1 + 5 + 0 + UNIT_EXECUTIVE_6 + + + UNITCLASS_EXECUTIVE_7 + TXT_KEY_UNIT_EXECUTIVE_7 + -1 + -1 + 5 + 0 + UNIT_EXECUTIVE_7 + + + UNITCLASS_JEWISH_MISSIONARY + TXT_KEY_UNIT_JEWISH_MISSIONARY + -1 + -1 + 5 + 0 + UNIT_JEWISH_MISSIONARY + + + UNITCLASS_CHRISTIAN_MISSIONARY + TXT_KEY_UNIT_CHRISTIAN_MISSIONARY + -1 + -1 + 5 + 0 + UNIT_CHRISTIAN_MISSIONARY + + + UNITCLASS_ISLAMIC_MISSIONARY + TXT_KEY_UNIT_ISLAMIC_MISSIONARY + -1 + -1 + 5 + 0 + UNIT_ISLAMIC_MISSIONARY + + + UNITCLASS_HINDU_MISSIONARY + TXT_KEY_UNIT_HINDU_MISSIONARY + -1 + -1 + 5 + 0 + UNIT_HINDU_MISSIONARY + + + UNITCLASS_BUDDHIST_MISSIONARY + TXT_KEY_UNIT_BUDDHIST_MISSIONARY + -1 + -1 + 5 + 0 + UNIT_BUDDHIST_MISSIONARY + + + UNITCLASS_CONFUCIAN_MISSIONARY + TXT_KEY_UNIT_CONFUCIAN_MISSIONARY + -1 + -1 + 5 + 0 + UNIT_CONFUCIAN_MISSIONARY + + + UNITCLASS_TAOIST_MISSIONARY + TXT_KEY_UNIT_TAOIST_MISSIONARY + -1 + -1 + 5 + 0 + UNIT_TAOIST_MISSIONARY + + + UNITCLASS_WARRIOR + TXT_KEY_UNIT_WARRIOR + -1 + -1 + -1 + 0 + UNIT_WARRIOR + + + UNITCLASS_SWORDSMAN + TXT_KEY_UNIT_SWORDSMAN + -1 + -1 + -1 + 0 + UNIT_SWORDSMAN + + + UNITCLASS_AXEMAN + TXT_KEY_UNIT_AXEMAN + -1 + -1 + -1 + 0 + UNIT_AXEMAN + + + UNITCLASS_MACEMAN + TXT_KEY_UNIT_MACEMAN + -1 + -1 + -1 + 0 + UNIT_MACEMAN + + + UNITCLASS_SPEARMAN + TXT_KEY_UNIT_SPEARMAN + -1 + -1 + -1 + 0 + UNIT_SPEARMAN + + + UNITCLASS_PIKEMAN + TXT_KEY_UNIT_PIKEMAN + -1 + -1 + -1 + 0 + UNIT_PIKEMAN + + + UNITCLASS_MUSKETMAN + TXT_KEY_UNIT_MUSKETMAN + -1 + -1 + -1 + 0 + UNIT_MUSKETMAN + + + UNITCLASS_RIFLEMAN + TXT_KEY_UNIT_RIFLEMAN + -1 + -1 + -1 + 0 + UNIT_RIFLEMAN + + + UNITCLASS_GRENADIER + TXT_KEY_UNIT_GRENADIER + -1 + -1 + -1 + 0 + UNIT_GRENADIER + + + UNITCLASS_INFANTRY + TXT_KEY_UNIT_INFANTRY + -1 + -1 + -1 + 0 + UNIT_INFANTRY + + + UNITCLASS_AT_INFANTRY + TXT_KEY_UNIT_AT_INFANTRY + -1 + -1 + -1 + 0 + UNIT_AT_INFANTRY + + + UNITCLASS_SAM_INFANTRY + TXT_KEY_UNIT_SAM_INFANTRY + -1 + -1 + -1 + 0 + UNIT_SAM_INFANTRY + + + UNITCLASS_MOBILE_SAM + TXT_KEY_UNIT_MOBILE_SAM + -1 + -1 + -1 + 0 + UNIT_MOBILE_SAM + + + UNITCLASS_MARINE + TXT_KEY_UNIT_MARINE + -1 + -1 + -1 + 0 + UNIT_MARINE + + + UNITCLASS_PARATROOPER + TXT_KEY_UNIT_PARATROOPER + -1 + -1 + -1 + 0 + UNIT_PARATROOPER + + + UNITCLASS_MECHANIZED_INFANTRY + TXT_KEY_UNIT_MECHANIZED_INFANTRY + -1 + -1 + -1 + 0 + UNIT_MECHANIZED_INFANTRY + + + UNITCLASS_ARCHER + TXT_KEY_UNIT_ARCHER + -1 + -1 + -1 + 0 + UNIT_ARCHER + + + UNITCLASS_LONGBOWMAN + TXT_KEY_UNIT_LONGBOWMAN + -1 + -1 + -1 + 0 + UNIT_LONGBOWMAN + + + UNITCLASS_CROSSBOWMAN + TXT_KEY_UNIT_CROSSBOWMAN + -1 + -1 + -1 + 0 + UNIT_CROSSBOWMAN + + + UNITCLASS_CHARIOT + TXT_KEY_UNIT_CHARIOT + -1 + -1 + -1 + 0 + UNIT_CHARIOT + + + UNITCLASS_HORSE_ARCHER + TXT_KEY_UNIT_HORSE_ARCHER + -1 + -1 + -1 + 0 + UNIT_HORSE_ARCHER + + + UNITCLASS_KNIGHT + TXT_KEY_UNIT_KNIGHT + -1 + -1 + -1 + 0 + UNIT_KNIGHT + + + UNITCLASS_CUIRASSIER + TXT_KEY_UNIT_CUIRASSIER + -1 + -1 + -1 + 0 + UNIT_CUIRASSIER + + + UNITCLASS_CAVALRY + TXT_KEY_UNIT_CAVALRY + -1 + -1 + -1 + 0 + UNIT_CAVALRY + + + UNITCLASS_WAR_ELEPHANT + TXT_KEY_UNIT_WAR_ELEPHANT + -1 + -1 + -1 + 0 + UNIT_WAR_ELEPHANT + + + UNITCLASS_TANK + TXT_KEY_UNIT_TANK + -1 + -1 + -1 + 0 + UNIT_TANK + + + UNITCLASS_MODERN_ARMOR + TXT_KEY_UNIT_MODERN_ARMOR + -1 + -1 + -1 + 0 + UNIT_MODERN_ARMOR + + + UNITCLASS_GUNSHIP + TXT_KEY_UNIT_GUNSHIP + -1 + -1 + -1 + 0 + UNIT_GUNSHIP + + + UNITCLASS_CATAPULT + TXT_KEY_UNIT_CATAPULT + -1 + -1 + -1 + 0 + UNIT_CATAPULT + + + UNITCLASS_TREBUCHET + TXT_KEY_UNIT_TREBUCHET + -1 + -1 + -1 + 0 + UNIT_TREBUCHET + + + UNITCLASS_CANNON + TXT_KEY_UNIT_CANNON + -1 + -1 + -1 + 0 + UNIT_CANNON + + + UNITCLASS_MACHINE_GUN + TXT_KEY_UNIT_MACHINE_GUN + -1 + -1 + -1 + 0 + UNIT_MACHINE_GUN + + + UNITCLASS_ARTILLERY + TXT_KEY_UNIT_ARTILLERY + -1 + -1 + -1 + 0 + UNIT_ARTILLERY + + + UNITCLASS_MOBILE_ARTILLERY + TXT_KEY_UNIT_MOBILE_ARTILLERY + -1 + -1 + -1 + 0 + UNIT_MOBILE_ARTILLERY + + + UNITCLASS_WORKBOAT + TXT_KEY_UNIT_WORK_BOAT + -1 + -1 + -1 + 0 + UNIT_WORKBOAT + + + UNITCLASS_GALLEY + TXT_KEY_UNIT_GALLEY + -1 + -1 + -1 + 0 + UNIT_GALLEY + + + UNITCLASS_TRIREME + TXT_KEY_UNIT_TRIREME + -1 + -1 + -1 + 0 + UNIT_TRIREME + + + UNITCLASS_CARAVEL + TXT_KEY_UNIT_CARAVEL + -1 + -1 + -1 + 0 + UNIT_CARAVEL + + + UNITCLASS_GALLEON + TXT_KEY_UNIT_GALLEON + -1 + -1 + -1 + 0 + UNIT_GALLEON + + + UNITCLASS_PRIVATEER + TXT_KEY_UNIT_PRIVATEER + -1 + -1 + -1 + 0 + UNIT_PRIVATEER + + + UNITCLASS_FRIGATE + TXT_KEY_UNIT_FRIGATE + -1 + -1 + -1 + 0 + UNIT_FRIGATE + + + UNITCLASS_SHIP_OF_THE_LINE + TXT_KEY_SHIP_OF_THE_LINE + -1 + -1 + -1 + 0 + UNIT_SHIP_OF_THE_LINE + + + UNITCLASS_IRONCLAD + TXT_KEY_UNIT_IRONCLAD + -1 + -1 + -1 + 0 + UNIT_IRONCLAD + + + UNITCLASS_TRANSPORT + TXT_KEY_UNIT_TRANSPORT + -1 + -1 + -1 + 0 + UNIT_TRANSPORT + + + UNITCLASS_DESTROYER + TXT_KEY_UNIT_DESTROYER + -1 + -1 + -1 + 0 + UNIT_DESTROYER + + + UNITCLASS_STEALTH_DESTROYER + TXT_KEY_UNIT_STEALTH_DESTROYER + -1 + -1 + -1 + 0 + UNIT_STEALTH_DESTROYER + + + UNITCLASS_BATTLESHIP + TXT_KEY_UNIT_BATTLESHIP + -1 + -1 + -1 + 0 + UNIT_BATTLESHIP + + + UNITCLASS_MISSILE_CRUISER + TXT_KEY_UNIT_MISSILE_CRUISER + -1 + -1 + -1 + 0 + UNIT_MISSILE_CRUISER + + + UNITCLASS_SUBMARINE + TXT_KEY_UNIT_SUBMARINE + -1 + -1 + -1 + 0 + UNIT_SUBMARINE + + + UNITCLASS_ATTACK_SUBMARINE + TXT_KEY_UNIT_ATTACK_SUBMARINE + -1 + -1 + -1 + 0 + UNIT_ATTACK_SUBMARINE + + + UNITCLASS_CARRIER + TXT_KEY_UNIT_CARRIER + -1 + -1 + -1 + 0 + UNIT_CARRIER + + + UNITCLASS_AIRSHIP + TXT_KEY_UNIT_AIRSHIP + -1 + -1 + -1 + 0 + UNIT_AIRSHIP + + + UNITCLASS_FIGHTER + TXT_KEY_UNIT_FIGHTER + -1 + -1 + -1 + 0 + UNIT_FIGHTER + + + UNITCLASS_JET_FIGHTER + TXT_KEY_UNIT_JET_FIGHTER + -1 + -1 + -1 + 0 + UNIT_JET_FIGHTER + + + UNITCLASS_BOMBER + TXT_KEY_UNIT_BOMBER + -1 + -1 + -1 + 0 + UNIT_BOMBER + + + UNITCLASS_STEALTH_BOMBER + TXT_KEY_UNIT_STEALTH_BOMBER + -1 + -1 + -1 + 0 + UNIT_STEALTH_BOMBER + + + UNITCLASS_GUIDED_MISSILE + TXT_KEY_UNIT_GUIDED_MISSILE + -1 + -1 + -1 + 0 + UNIT_GUIDED_MISSILE + + + UNITCLASS_ICBM + TXT_KEY_UNIT_ICBM + -1 + -1 + -1 + 0 + UNIT_ICBM + + + UNITCLASS_TACTICAL_NUKE + TXT_KEY_UNIT_TACTICAL_NUKE + -1 + -1 + -1 + 0 + UNIT_TACTICAL_NUKE + + + UNITCLASS_PROPHET + TXT_KEY_UNIT_GREAT_PROPHET + -1 + -1 + -1 + 0 + UNIT_PROPHET + + + UNITCLASS_ARTIST + TXT_KEY_UNIT_GREAT_ARTIST + -1 + -1 + -1 + 0 + UNIT_ARTIST + + + UNITCLASS_SCIENTIST + TXT_KEY_UNIT_GREAT_SCIENTIST + -1 + -1 + -1 + 0 + UNIT_SCIENTIST + + + UNITCLASS_MERCHANT + TXT_KEY_UNIT_GREAT_TYCOON + -1 + -1 + -1 + 0 + UNIT_MERCHANT + + + UNITCLASS_ENGINEER + TXT_KEY_UNIT_GREAT_ENGINEER + -1 + -1 + -1 + 0 + UNIT_ENGINEER + + + UNITCLASS_GREAT_GENERAL + TXT_KEY_UNIT_GREAT_GENERAL + -1 + -1 + -1 + 0 + UNIT_GREAT_GENERAL + + + UNITCLASS_GREAT_SPY + TXT_KEY_SPECIALIST_GREAT_SPY + -1 + -1 + -1 + 0 + UNIT_GREAT_SPY + + + diff --git a/Mod/RB Mod/Assets/XML/Units/CIV4UnitInfos.xml b/Mod/RB Mod/Assets/XML/Units/CIV4UnitInfos.xml index 2ea4aa9..23c379d 100644 --- a/Mod/RB Mod/Assets/XML/Units/CIV4UnitInfos.xml +++ b/Mod/RB Mod/Assets/XML/Units/CIV4UnitInfos.xml @@ -5,7 +5,7 @@ - + UNITCLASS_LION UNIT_LION @@ -111,7 +111,7 @@ - 2 + 1 100 0 0 @@ -151,7 +151,12 @@ - + + + UNITCOMBAT_MELEE + 50 + + @@ -291,7 +296,7 @@ - 3 + 1 100 0 0 @@ -323,7 +328,12 @@ - + + + UNITCOMBAT_MELEE + 100 + + @@ -463,7 +473,7 @@ - 2 + 1 100 0 0 @@ -526,7 +536,7 @@ 0 0 0 - + PROMOTION_WOODSMAN2 NONE 0 @@ -940,7 +950,12 @@ 0 0 0 - + + + UNITCLASS_FAST_WORKER + 1 + + @@ -1300,7 +1315,7 @@ NONE NONE NONE - NONE + NONE @@ -1323,7 +1338,7 @@ 0 0 -1 - 100 + 125 0 0 0 @@ -1529,7 +1544,7 @@ 0 0 0 - 100 + 200 0 0 @@ -5968,8 +5983,16 @@ + + UNITCLASS_ARCHER + -40 + + + UNITCLASS_ARCHER + -40 + @@ -7469,7 +7492,7 @@ 0 4 2 - 1 + 2 0 0 0 @@ -7534,10 +7557,6 @@ PROMOTION_DRILL1 1 - - PROMOTION_DRILL2 - 1 - NONE 0 @@ -8813,7 +8832,7 @@ 2 0 0 - 75 + 70 0 0 0 @@ -11079,6 +11098,10 @@ UNITCLASS_AXEMAN 100 + + UNITCLASS_ARCHER + -25 + @@ -15539,7 +15562,7 @@ TXT_KEY_UNIT_WORK_BOAT_STRATEGY ADVISOR_ECONOMY 0 - 0 + 1 0 0 0 @@ -15570,7 +15593,7 @@ 0 1 1 - 0 + 1 0 0 @@ -15611,7 +15634,7 @@ NONE NONE NONE - TECH_FISHING + NONE NONE @@ -15623,7 +15646,7 @@ 0 - 30 + 25 0 100 0