Code
6832/// Moves units to the hex with the lowest danger6833void CvTacticalAI::ExecuteMovesToSafestPlot()6834{6835 int iDanger;68366837#if defined(PATH_PLAN_LAST)6838 // Maybe make these part of the class and just reuse?6839 WeightedPlotVector aCityList;6840 aCityList.reserve(10);6841 WeightedPlotVector aZeroDangerList;6842 aZeroDangerList.reserve(100);6843 WeightedPlotVector aCoverList;6844 aCoverList.reserve(100);6845 WeightedPlotVector aDangerList;6846 aDangerList.reserve(100);6847#endif68486849 TeamTypes ePlayerTeam = m_pPlayer->getTeam();6850 PlayerTypes ePlayerID = m_pPlayer->GetID();68516852 for(unsigned int iI = 0; iI < m_CurrentMoveUnits.size(); iI++)6853 {6854 UnitHandle pUnit = m_pPlayer->getUnit(m_CurrentMoveUnits[iI].GetID());6855 if(pUnit)6856 {6857#if defined(PATH_PLAN_LAST)6858 aCityList.clear();6859 aZeroDangerList.clear();6860 aCoverList.clear();6861 aDangerList.clear();6862#endif6863 CvPlot* pBestPlot = NULL;68646865 int iRange = pUnit->getUnitInfo().GetMoves();6866#if !defined(PATH_PLAN_LAST)6867 int iLowestDanger = MAX_INT;6868 bool bResultHasZeroDangerMove = false;6869 bool bResultInTerritory = false;6870 bool bResultInCity = false;6871 bool bResultInCover = false;6872#endif68736874 CvMap& kMap = GC.getMap();6875 int iUnitX = pUnit->getX();6876 int iUnitY = pUnit->getY();6877 DomainTypes eUnitDomain = pUnit->getDomainType();6878 bool bIsSeaUnit = eUnitDomain == DOMAIN_SEA;68796880 // For each plot within movement range of the fleeing unit6881 for(int iX = -iRange; iX <= iRange; iX++)6882 {6883 for(int iY = -iRange; iY <= iRange; iY++)6884 {6885 CvPlot* pPlot = kMap.plot(iUnitX + iX, iUnitY + iY);6886 if(pPlot == NULL)6887 {6888 continue;6889 }68906891 // Can't be a plot with another player's unit in it or another of our unit of same type6892 if(pPlot->getNumUnits() > 0)6893 {6894 IDInfo* pUnitNode = pPlot->headUnitNode();6895 if(pUnitNode)6896 {6897 CvUnit* pFirstUnit = ::getUnit(*pUnitNode);6898 if(pFirstUnit)6899 {6900 if(pFirstUnit->getOwner() != pUnit->getOwner())6901 {6902 continue;6903 }69046905 else if(pUnit->AreUnitsOfSameType(*pFirstUnit))6906 {6907 continue;6908 }6909 }6910 }6911 }69126913 // Also filter out sea units targeting land plots6914 if (bIsSeaUnit && !pPlot->isWater())6915 {6916 continue;6917 }69186919#if !defined(PATH_PLAN_LAST)6920 if(!CanReachInXTurns(pUnit, pPlot, 1))6921 {6922 continue;6923 }6924#endif6925 // prefer being in a city with the lowest danger value6926 // prefer being in a plot with no danger value6927 // prefer being under a unit with the lowest danger value6928 // prefer being in your own territory with the lowest danger value6929 // prefer the lowest danger value69306931 iDanger = m_pPlayer->GetPlotDanger(*pPlot);6932 bool bIsZeroDanger = (iDanger <= 0);6933 bool bIsInCity = pPlot->isFriendlyCity(*pUnit, false);6934 bool bIsInCover = (pPlot->getNumDefenders(ePlayerID) > 0) && !pUnit->IsCanDefend(pPlot); // only move to cover if I'm defenseless here6935 bool bIsInTerritory = (pPlot->getTeam() == ePlayerTeam);6936#if defined(MOD_AI_SMART_V3) 6937 bool bNeedEmbark = ((eUnitDomain == DOMAIN_LAND) && (!pUnit->plot()->isWater()) && (pPlot->isWater()));6938#endif69396940#if defined(PATH_PLAN_LAST)6941#if defined(MOD_AI_SMART_V3) 6942 // AMS: Enormous danger on water plot, embarking as last option.6943 if(MOD_AI_SMART_V3 && bNeedEmbark && !bIsInCover)6944 {6945 int combatMod = pUnit->GetBaseCombatStrength() == 0 ? 100 : pUnit->GetBaseCombatStrength();6946 iDanger = min(combatMod * 900, 99999);6947 aDangerList.push_back(pPlot, iDanger);6948 }6949 else6950#endif6951 if(bIsInCity)6952 {6953 aCityList.push_back(pPlot, iDanger);6954 }6955 else6956 if(bIsZeroDanger)6957 {6958 aZeroDangerList.push_back(pPlot, (bIsInTerritory)?0:1);6959 }6960 else6961 if(bIsInCover)6962 {6963 aCoverList.push_back(pPlot, iDanger);6964 }6965 else6966 {6967 aDangerList.push_back(pPlot, iDanger);6968 }6969#endif69706971#if !defined(PATH_PLAN_LAST)6972 bool bUpdateBestValue = false;69736974 if(bIsInCity)6975 {6976 if(!bResultInCity || iDanger < iLowestDanger)6977 {6978 bUpdateBestValue = true;6979 }6980 }6981 else if(bIsZeroDanger)6982 {6983 if(!bResultInCity)6984 {6985 if(bResultHasZeroDangerMove)6986 {6987 if(bIsInTerritory && !bResultInTerritory)6988 {6989 bUpdateBestValue = true;6990 }6991 }6992 else6993 {6994 bUpdateBestValue = true;6995 }6996 }6997 }6998 else if(bIsInCover)6999 {7000 if(!bResultInCity && !bResultHasZeroDangerMove)7001 {7002 if(!bResultInCover || iDanger < iLowestDanger)7003 {7004 bUpdateBestValue = true;7005 }7006 }7007 }7008 else if(bIsInTerritory)7009 {7010 if(!bResultInCity && !bResultInCover && !bResultHasZeroDangerMove)7011 {7012 if(!bResultInTerritory || iDanger < iLowestDanger)7013 {7014 bUpdateBestValue = true;7015 }7016 }7017 }7018 // if we have no good home, head to the lowest danger value7019 else if(!bResultInCity && !bResultInCover && !bResultInTerritory && !bResultHasZeroDangerMove)7020 {7021 if(iDanger < iLowestDanger)7022 {7023 bUpdateBestValue = true;7024 }7025 }70267027 if(bUpdateBestValue)7028 {7029 pBestPlot = pPlot;7030 iLowestDanger = iDanger;70317032 bResultInTerritory = bIsInTerritory;7033 bResultInCity = bIsInCity;7034 bResultInCover = bIsInCover;7035 bResultHasZeroDangerMove = bIsZeroDanger;7036 }7037#endif7038 }7039 }70407041#if defined(PATH_PLAN_LAST)7042 // Now that we've gathered up our lists of destinations, go through them in order and pick the first one we can reach.7043 // This minimizes accessing the pathfinder.7044 if ((pBestPlot = GetReachablePlot(pUnit, aCityList, 1)) == NULL)7045 if ((pBestPlot = GetReachablePlot(pUnit, aZeroDangerList, 1)) == NULL)7046 if ((pBestPlot = GetReachablePlot(pUnit, aCoverList, 1)) == NULL)7047 pBestPlot = GetReachablePlot(pUnit, aDangerList, 1);7048#endif70497050 if(pBestPlot != NULL)7051 {7052 // Move to the lowest danger value found7053 pUnit->PushMission(CvTypes::getMISSION_MOVE_TO(), pBestPlot->getX(), pBestPlot->getY(), MOVE_UNITS_IGNORE_DANGER);7054 pUnit->finishMoves();7055 UnitProcessed(pUnit->GetID(), pUnit->IsCombatUnit());70567057 if(GC.getLogging() && GC.getAILogging())7058 {7059 CvString strLogString;7060 CvString strTemp;7061 strTemp = GC.getUnitInfo(pUnit->getUnitType())->GetDescription();7062 strLogString.Format("Moving %s to safety, To X: %d, Y: %d, From X: %d, Y: %d", strTemp.GetCString(), pBestPlot->getX(), pBestPlot->getY(), pUnit->getX(), pUnit->getY());7063 LogTacticalMessage(strLogString);7064 }7065 }7066 else7067 {7068 if(GC.getLogging() && GC.getAILogging())7069 {7070 CvString strLogString;7071 CvString strTemp;7072 strTemp = GC.getUnitInfo(pUnit->getUnitType())->GetDescription();7073 strLogString.Format("Failed to find destination moving %s to safety from, X: %d, Y: %d", strTemp.GetCString(), pUnit->getX(), pUnit->getY());7074 LogTacticalMessage(strLogString);7075 }7076 }7077 }7078 }7079}