void CvMapGenerator::addGoodies() { PROFILE_FUNC(); if (gDLL->getPythonIFace()->pythonAddGoodies() && !gDLL->getPythonIFace()->pythonUsingDefaultImpl()) { return; // Python override } gDLL->NiTextOut("Adding Goodies..."); if (GC.getEraInfo(GC.getGameINLINE().getStartEra()).isNoGoodies()) { return; } int iNumPlots = GC.getMapINLINE().numPlotsINLINE(); std::vector<int> aiShuffle(iNumPlots); GC.getGameINLINE().getMapRand().shuffleSequence(aiShuffle, "addNonUniqueBonusType shuffle"); for (int iI = 0; iI < GC.getNumImprovementInfos(); iI++) { if (GC.getImprovementInfo((ImprovementTypes)iI).isGoody() && GC.getImprovementInfo((ImprovementTypes)iI).getTilesPerGoody() > 0) { for (int iJ = 0; iJ < iNumPlots; iJ++) { gDLL->callUpdater(); CvPlot *pPlot = GC.getMapINLINE().plotByIndexINLINE(aiShuffle[iJ]); FAssertMsg(pPlot, "pPlot is expected not to be NULL"); if (!(pPlot->isWater())) { CvArea *pArea = GC.getMapINLINE().getArea(pPlot->getArea()); FAssertMsg(pArea, "pArea is expected not to be NULL"); if (pArea->getNumImprovements((ImprovementTypes)iI) < ((pArea->getNumTiles() + (GC.getImprovementInfo((ImprovementTypes)iI).getTilesPerGoody() / 2)) / GC.getImprovementInfo((ImprovementTypes) iI).getTilesPerGoody())) { if (canPlaceGoodyAt(((ImprovementTypes)iI), pPlot->getX_INLINE(), pPlot->getY_INLINE())) { pPlot->setImprovementType((ImprovementTypes)iI); } } } } } } }
void CvPlayerAI::AI_updateFoundValues(bool bStartingLoc) { int iLoop; const int iNumPlots = GC.getMap().numPlots(); for(CvArea *pLoopArea = GC.getMap().firstArea(&iLoop); pLoopArea != NULL; pLoopArea = GC.getMap().nextArea(&iLoop)) { pLoopArea->setTotalFoundValue(0); } const PlayerTypes eID = GetID(); if (bStartingLoc) { for (int iI = 0; iI < iNumPlots; iI++) { GC.getMap().plotByIndexUnchecked(iI)->setFoundValue(eID, -1); } } else { const TeamTypes eTeam = getTeam(); for (int iI = 0; iI < iNumPlots; iI++) { CvPlot* pLoopPlot = GC.getMap().plotByIndexUnchecked(iI); if (pLoopPlot->isRevealed(eTeam)) { const int iValue = AI_foundValue(pLoopPlot->getX(), pLoopPlot->getY()); pLoopPlot->setFoundValue(eID, iValue); CvArea *pLoopArea = GC.getMap().getArea(pLoopPlot->getArea()); if (pLoopArea && !pLoopArea->isWater()) { pLoopArea->setTotalFoundValue(pLoopArea->getTotalFoundValue() + iValue); } } else { pLoopPlot->setFoundValue(eID, -1); } } } }
int CvArea::countCoastalLand() const { if (isWater()) { return 0; } int iCount = 0; for (int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++) { CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI); if (pLoopPlot->getArea() == getID()) { if (pLoopPlot->isCoastalLand()) { iCount++; } } } return iCount; }
/// Add data for this cell into dominance zone information void CvTacticalAnalysisMap::AddToDominanceZones(int iIndex, CvTacticalAnalysisCell* pCell) { TeamTypes ourTeam = GET_PLAYER(m_ePlayer).getTeam(); CvPlot* pPlot = GC.getMap().plotByIndex(iIndex); // Compute zone data for this cell CvTacticalDominanceZone newZone; newZone.SetAreaID(pPlot->getArea()); newZone.SetWater(pPlot->isWater()); int iCityDistance = GC.getGame().GetClosestCityDistanceInTurns(pPlot); CvCity* pCity = GC.getGame().GetClosestCityByEstimatedTurns(pPlot); PlayerTypes eOwnerPlayer = NO_PLAYER; TeamTypes eOwnerTeam = NO_TEAM; //for plots far away from a city, check the owner if (iCityDistance>2) { eOwnerTeam = pPlot->getTeam(); eOwnerPlayer = pPlot->getOwner(); //there is almost always a closest city, but we're not always interested if (pCity && eOwnerPlayer!=pCity->getOwner()) pCity = NULL; } else if (pCity) //look at the city { eOwnerTeam = pCity->getTeam(); eOwnerPlayer = pCity->getOwner(); } newZone.SetOwner(eOwnerPlayer); newZone.SetZoneCity(pCity); newZone.Extend(pPlot); if(eOwnerTeam==NO_TEAM) { newZone.SetTerritoryType(TACTICAL_TERRITORY_NO_OWNER); } else if(eOwnerTeam == ourTeam) { newZone.SetTerritoryType(TACTICAL_TERRITORY_FRIENDLY); } else if(GET_TEAM(ourTeam).isAtWar(eOwnerTeam)) { newZone.SetTerritoryType(TACTICAL_TERRITORY_ENEMY); } else { newZone.SetTerritoryType(TACTICAL_TERRITORY_NEUTRAL); } // Now see if we already have a matching zone CvTacticalDominanceZone* pZone = MergeWithExistingZone(&newZone); if(!pZone) { // Data populated, now add to vector newZone.SetDominanceZoneID(m_DominanceZones.size()); m_DominanceZones.push_back(newZone); pZone = &m_DominanceZones[m_DominanceZones.size() - 1]; } // Set zone for this cell pCell->SetDominanceZone(pZone->GetDominanceZoneID()); pZone->Extend(pPlot); }
///Tks Med CvPlot* CvMap::syncRandPlot(int iFlags, int iArea, int iMinUnitDistance, int iTimeout, bool bIgnoreNativeTeams) { ///TKe CvPlot* pPlot = NULL; int iCount = 0; while (iCount < iTimeout) { CvPlot* pTestPlot = plotSorenINLINE(GC.getGameINLINE().getSorenRandNum(getGridWidthINLINE(), "Rand Plot Width"), GC.getGameINLINE().getSorenRandNum(getGridHeightINLINE(), "Rand Plot Height")); FAssertMsg(pTestPlot != NULL, "TestPlot is not assigned a valid value"); if ((iArea == -1) || (pTestPlot->getArea() == iArea)) { bool bValid = true; if (bValid) { if (iMinUnitDistance != -1) { for (int iDX = -(iMinUnitDistance); iDX <= iMinUnitDistance; iDX++) { for (int iDY = -(iMinUnitDistance); iDY <= iMinUnitDistance; iDY++) { CvPlot* pLoopPlot = plotXY(pTestPlot->getX_INLINE(), pTestPlot->getY_INLINE(), iDX, iDY); if (pLoopPlot != NULL) { if (pLoopPlot->isUnit()) { bValid = false; } } } } } } if (bValid) { if (iFlags & RANDPLOT_LAND) { if (pTestPlot->isWater()) { bValid = false; } } } if (bValid) { if (iFlags & RANDPLOT_UNOWNED) { if (pTestPlot->isOwned()) { ///Tks Med if (bIgnoreNativeTeams) { if (!GET_PLAYER(pTestPlot->getOwnerINLINE()).isNative()) { bValid = false; } } else { bValid = false; } ///TKe } } } if (bValid) { if (iFlags & RANDPLOT_ADJACENT_UNOWNED) { if (pTestPlot->isAdjacentOwned()) { bValid = false; } } } if (bValid) { if (iFlags & RANDPLOT_ADJACENT_LAND) { if (!(pTestPlot->isAdjacentToLand())) { bValid = false; } } } if (bValid) { if (iFlags & RANDPLOT_PASSIBLE) { if (pTestPlot->isImpassable()) { bValid = false; } } } if (bValid) { if (iFlags & RANDPLOT_NOT_VISIBLE_TO_CIV) { ///TKs Med if (pTestPlot->isVisibleToCivTeam(bIgnoreNativeTeams)) { bValid = false; } ///TKe } } ///TKs Med if (bValid) { if (bIgnoreNativeTeams) { if (pTestPlot->isVisibleToWatchingHuman()) { bValid = false; } } } ///TKe if (bValid) { if (iFlags & RANDPLOT_NOT_CITY) { if (pTestPlot->isCity()) { bValid = false; } } } if (bValid) { pPlot = pTestPlot; break; } } iCount++; } return pPlot; }
/// Add data for this cell into dominance zone information void CvTacticalAnalysisMap::AddToDominanceZones(int iIndex, CvTacticalAnalysisCell* pCell) { CvPlot* pPlot = GC.getMap().plotByIndex(iIndex); // Compute zone data for this cell m_TempZone.SetAreaID(pPlot->getArea()); m_TempZone.SetOwner(pPlot->getOwner()); m_TempZone.SetWater(pPlot->isWater()); if(!pPlot->isOwned()) { m_TempZone.SetTerritoryType(TACTICAL_TERRITORY_NO_OWNER); } else if(pPlot->getTeam() == m_pPlayer->getTeam()) { m_TempZone.SetTerritoryType(TACTICAL_TERRITORY_FRIENDLY); } else if(GET_TEAM(m_pPlayer->getTeam()).isAtWar(pPlot->getTeam())) { m_TempZone.SetTerritoryType(TACTICAL_TERRITORY_ENEMY); } else { m_TempZone.SetTerritoryType(TACTICAL_TERRITORY_NEUTRAL); } m_TempZone.SetClosestCity(NULL); if(m_TempZone.GetTerritoryType() == TACTICAL_TERRITORY_ENEMY || m_TempZone.GetTerritoryType() == TACTICAL_TERRITORY_NEUTRAL || m_TempZone.GetTerritoryType() == TACTICAL_TERRITORY_FRIENDLY) { int iLoop; int iBestDistance = MAX_INT; CvCity* pBestCity = NULL; for(CvCity* pLoopCity = GET_PLAYER(m_TempZone.GetOwner()).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER(m_TempZone.GetOwner()).nextCity(&iLoop)) { int iDistance = plotDistance(pLoopCity->getX(), pLoopCity->getY(), pPlot->getX(), pPlot->getY()); if(iDistance < iBestDistance) { iBestDistance = iDistance; pBestCity = pLoopCity; } } if(pBestCity != NULL) { m_TempZone.SetClosestCity(pBestCity); } } // Now see if we already have a matching zone CvTacticalDominanceZone* pZone = FindExistingZone(pPlot); if(!pZone) { // Data populated, now add to vector m_TempZone.SetDominanceZoneID(m_DominanceZones.size()); m_DominanceZones.push_back(m_TempZone); pZone = &m_DominanceZones[m_DominanceZones.size() - 1]; } // If this isn't owned territory, update zone with military strength info if(pZone->GetTerritoryType() == TACTICAL_TERRITORY_NO_OWNER || pZone->GetTerritoryType() == TACTICAL_TERRITORY_TEMP_ZONE) { CvUnit* pFriendlyUnit = pCell->GetFriendlyMilitaryUnit(); if(pFriendlyUnit) { if(pFriendlyUnit->getDomainType() == DOMAIN_AIR || (pFriendlyUnit->getDomainType() == DOMAIN_LAND && !pZone->IsWater()) || (pFriendlyUnit->getDomainType() == DOMAIN_SEA && pZone->IsWater())) { int iStrength = pFriendlyUnit->GetBaseCombatStrengthConsideringDamage(); if(iStrength == 0 && pFriendlyUnit->isEmbarked() && !pZone->IsWater()) { iStrength = pFriendlyUnit->GetBaseCombatStrength(true); } pZone->AddFriendlyStrength(iStrength * m_iUnitStrengthMultiplier); pZone->AddFriendlyRangedStrength(pFriendlyUnit->GetMaxRangedCombatStrength(NULL, /*pCity*/ NULL, true, true)); if(pFriendlyUnit->GetRange() > GetBestFriendlyRange()) { SetBestFriendlyRange(pFriendlyUnit->GetRange()); } if(pFriendlyUnit->IsRangeAttackIgnoreLOS()) { SetIgnoreLOS(true); } pZone->AddFriendlyUnitCount(1); if(pFriendlyUnit->isRanged()) { pZone->AddFriendlyRangedUnitCount(1); } } } CvUnit* pEnemyUnit = pCell->GetEnemyMilitaryUnit(); if(pEnemyUnit) { if(pEnemyUnit->getDomainType() == DOMAIN_AIR || (pEnemyUnit->getDomainType() == DOMAIN_LAND && !pZone->IsWater()) || (pEnemyUnit->getDomainType() == DOMAIN_SEA && pZone->IsWater())) { int iStrength = pEnemyUnit->GetBaseCombatStrengthConsideringDamage(); if(iStrength == 0 && pEnemyUnit->isEmbarked() && !pZone->IsWater()) { iStrength = pEnemyUnit->GetBaseCombatStrength(true); } #if defined(MOD_AI_SMART_V3) int iEnemyRangedStrength = pEnemyUnit->GetMaxRangedCombatStrength(NULL, /*pCity*/ NULL, true, true); if (MOD_AI_SMART_V3) { if (!pCell->IsVisible()) { iStrength /= 2; iEnemyRangedStrength /= 2; } iEnemyRangedStrength = iEnemyRangedStrength * m_iUnitStrengthMultiplier; } #endif pZone->AddEnemyStrength(iStrength * m_iUnitStrengthMultiplier); #if defined(MOD_AI_SMART_V3) pZone->AddEnemyRangedStrength(iEnemyRangedStrength); #else pZone->AddEnemyRangedStrength(pEnemyUnit->GetMaxRangedCombatStrength(NULL, /*pCity*/ NULL, true, true)); #endif pZone->AddEnemyUnitCount(1); if(pEnemyUnit->isRanged()) { pZone->AddEnemyRangedUnitCount(1); } if (pEnemyUnit->getDomainType() == DOMAIN_SEA) { pZone->AddEnemyNavalUnitCount(1); } } } } // Set zone for this cell pCell->SetDominanceZone(pZone->GetDominanceZoneID()); }
// Indicate the plots we might want to move to that the enemy can attack void CvTacticalAnalysisMap::MarkCellsNearEnemy() { int iDistance; // Look at every cell on the map for(int iI = 0; iI < GC.getMap().numPlots(); iI++) { bool bMarkedIt = false; // Set true once we've found one that enemy can move past (worst case) CvPlot* pPlot = GC.getMap().plotByIndexUnchecked(iI); if(m_pPlots[iI].IsRevealed() && !m_pPlots[iI].IsImpassableTerrain() && !m_pPlots[iI].IsImpassableTerritory()) { // Friendly cities always safe if(!m_pPlots[iI].IsFriendlyCity()) { if(!pPlot->isVisibleToEnemyTeam(m_pPlayer->getTeam())) { m_pPlots[iI].SetNotVisibleToEnemy(true); } else { for(unsigned int iUnitIndex = 0; iUnitIndex < m_EnemyUnits.size() && !bMarkedIt; iUnitIndex++) { CvUnit* pUnit = m_EnemyUnits[iUnitIndex]; if(pUnit->getArea() == pPlot->getArea()) { // Distance check before hitting pathfinder iDistance = plotDistance(pUnit->getX(), pUnit->getY(), pPlot->getX(), pPlot->getY()); if(iDistance == 0) { m_pPlots[iI].SetSubjectToAttack(true); m_pPlots[iI].SetEnemyCanMovePast(true); bMarkedIt = true; } // TEMPORARY OPTIMIZATION: Assumes can't use roads or RR else if(iDistance <= pUnit->baseMoves()) { int iTurnsToReach; iTurnsToReach = TurnsToReachTarget(pUnit, pPlot, true /*bReusePaths*/, true /*bIgnoreUnits*/); // Its ok to reuse paths because when ignoring units, we don't use the tactical analysis map (which we are building) if(iTurnsToReach <= 1) { m_pPlots[iI].SetSubjectToAttack(true); } if(iTurnsToReach == 0) { m_pPlots[iI].SetEnemyCanMovePast(true); bMarkedIt = true; } } } } // Check adjacent plots for enemy citadels if(!m_pPlots[iI].IsSubjectToAttack()) { CvPlot* pAdjacentPlot; for(int jJ = 0; jJ < NUM_DIRECTION_TYPES; jJ++) { pAdjacentPlot = plotDirection(pPlot->getX(), pPlot->getY(), ((DirectionTypes)jJ)); if(pAdjacentPlot != NULL && pAdjacentPlot->getOwner() != NO_PLAYER) { if(atWar(m_pPlayer->getTeam(), GET_PLAYER(pAdjacentPlot->getOwner()).getTeam())) { ImprovementTypes eImprovement = pAdjacentPlot->getImprovementType(); if(eImprovement != NO_IMPROVEMENT && GC.getImprovementInfo(eImprovement)->GetNearbyEnemyDamage() > 0) { m_pPlots[iI].SetSubjectToAttack(true); break; } } } } } } } } } }