void CvMap::updateMinOriginalStartDist(CvArea* pArea) { PROFILE_FUNC(); CvPlot* pStartingPlot; CvPlot* pLoopPlot; int iDist; int iI, iJ; for (iI = 0; iI < numPlotsINLINE(); iI++) { pLoopPlot = plotByIndexINLINE(iI); if (pLoopPlot->area() == pArea) { pLoopPlot->setMinOriginalStartDist(-1); } } for (iI = 0; iI < MAX_PLAYERS; iI++) { pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot(); if (pStartingPlot != NULL) { if (pStartingPlot->area() == pArea) { for (iJ = 0; iJ < numPlotsINLINE(); iJ++) { pLoopPlot = plotByIndexINLINE(iJ); if (pLoopPlot->area() == pArea) { //iDist = GC.getMapINLINE().calculatePathDistance(pStartingPlot, pLoopPlot); iDist = stepDistance(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE()); if (iDist != -1) { //int iCrowDistance = plotDistance(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE()); //iDist = std::min(iDist, iCrowDistance * 2); if ((pLoopPlot->getMinOriginalStartDist() == -1) || (iDist < pLoopPlot->getMinOriginalStartDist())) { pLoopPlot->setMinOriginalStartDist(iDist); } } } } } } } }
CvPlot* CvArmyAI::CheckTargetReached(PlayerTypes eEnemy, bool bNavalOp, int iMaxDistance) { //check if we're at the target CvPlot *pTargetPlot = GetGoalPlot(); CvPlot *pCenterOfMass = GetCenterOfMass(NO_DOMAIN); if(pCenterOfMass && pTargetPlot && plotDistance(*pCenterOfMass,*pTargetPlot) <= iMaxDistance) return pTargetPlot; //check early termination if we ran into the enemy if(GetArmyAIState() == ARMYAISTATE_MOVING_TO_DESTINATION) { CvPlot* pEnemyPlot = DetectNearbyEnemy(eEnemy, bNavalOp); if(pEnemyPlot != NULL) { CvCity* pCity = pEnemyPlot->getWorkingCity(); if(pCity != NULL) { if (bNavalOp && pCity->isCoastal() && pCity->waterArea()==pTargetPlot->area()) pEnemyPlot = pCity->plot(); if (!bNavalOp && pCity->area()==pTargetPlot->area()) pEnemyPlot = pCity->plot(); if (pEnemyPlot!=GetGoalPlot()) { if(GC.getLogging() && GC.getAILogging()) { CvString strMsg; strMsg.Format("Switching target from %d,%d to closest city at %d,%d", GetGoalX(), GetGoalY(), pEnemyPlot->getX(), pEnemyPlot->getY() ); GET_PLAYER(m_eOwner).getAIOperation(m_iOperationID)->LogOperationSpecialMessage(strMsg); } } return pEnemyPlot; } } } return NULL; }
void CvMapGenerator::addUniqueBonusType(BonusTypes eBonusType) { int* piAreaTried = new int[GC.getMapINLINE().getNumAreas()]; for (int iI = 0; iI < GC.getMapINLINE().getNumAreas(); iI++) { piAreaTried[iI] = FFreeList::INVALID_INDEX; } CvBonusInfo& pBonusInfo = GC.getBonusInfo(eBonusType); int iBonusCount = calculateNumBonusesToAdd(eBonusType); bool bIgnoreLatitude = false; gDLL->getPythonIFace()->pythonIsBonusIgnoreLatitudes(&bIgnoreLatitude); FAssertMsg(pBonusInfo.isOneArea(), "addUniqueBonusType called with non-unique bonus type"); while (true) { int iBestValue = 0; int iLoop = 0; CvArea *pBestArea = NULL; CvArea *pLoopArea = NULL; for(pLoopArea = GC.getMapINLINE().firstArea(&iLoop); pLoopArea != NULL; pLoopArea = GC.getMapINLINE().nextArea(&iLoop)) { bool bTried = false; for (int iI = 0; iI < GC.getMapINLINE().getNumAreas(); iI++) { if (pLoopArea->getID() == piAreaTried[iI]) { bTried = true; break; } } if (!bTried) { int iNumUniqueBonusesOnArea = pLoopArea->countNumUniqueBonusTypes() + 1; // number of unique bonuses starting on the area, plus this one int iNumTiles = pLoopArea->getNumTiles(); int iValue = iNumTiles / iNumUniqueBonusesOnArea; if (iValue > iBestValue) { iBestValue = iValue; pBestArea = pLoopArea; } } } if (pBestArea == NULL) { break; // can't place bonus on any area } for (int iI = 0; iI < GC.getMapINLINE().getNumAreas(); iI++) { if (piAreaTried[iI] == FFreeList::INVALID_INDEX) { piAreaTried[iI] = pBestArea->getID(); break; } } // Place the bonuses: std::vector<int> aiShuffle(GC.getMapINLINE().numPlotsINLINE()); GC.getGameINLINE().getMapRand().shuffleSequence(aiShuffle, "addUniqueBonusType shuffle"); for (int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++) { CvPlot* pPlot = GC.getMapINLINE().plotByIndexINLINE(aiShuffle[iI]); FAssertMsg(pPlot != NULL, "addUniqueBonusType(): pPlot is null"); if (GC.getMapINLINE().getNumBonuses(eBonusType) >= iBonusCount) { break; // We already have enough } if (pBestArea == pPlot->area()) { if (canPlaceBonusAt(eBonusType, pPlot->getX_INLINE(), pPlot->getY_INLINE(), bIgnoreLatitude)) { pPlot->setBonusType(eBonusType); for (int iDX = -(pBonusInfo.getGroupRange()); iDX <= pBonusInfo.getGroupRange(); iDX++) { for (int iDY = -(pBonusInfo.getGroupRange()); iDY <= pBonusInfo.getGroupRange(); iDY++) { if (GC.getMapINLINE().getNumBonuses(eBonusType) < iBonusCount) { CvPlot* pLoopPlot = plotXY(pPlot->getX_INLINE(), pPlot->getY_INLINE(), iDX, iDY); if (pLoopPlot != NULL && (pLoopPlot->area() == pBestArea)) { if (canPlaceBonusAt(eBonusType, pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), bIgnoreLatitude)) { if (GC.getGameINLINE().getMapRandNum(100, "addUniqueBonusType") < pBonusInfo.getGroupRand()) { pLoopPlot->setBonusType(eBonusType); } } } } } } } } } } SAFE_DELETE_ARRAY(piAreaTried); }
bool CvMapGenerator::canPlaceBonusAt(BonusTypes eBonus, int iX, int iY, bool bIgnoreLatitude) { PROFILE_FUNC(); CvArea* pArea; CvPlot* pPlot; CvPlot* pLoopPlot; int iRange; int iDX, iDY; int iI; pPlot = GC.getMapINLINE().plotINLINE(iX, iY); pArea = pPlot->area(); if (!(pPlot->canHaveBonus(eBonus, bIgnoreLatitude))) { return false; } long result = 0; if (gDLL->getPythonIFace()->pythonCanPlaceBonusAt(pPlot, &result) && !gDLL->getPythonIFace()->pythonUsingDefaultImpl()) // Python override { if (result >= 0) { return result; } else { FAssertMsg(false, "canPlaceBonusAt() must return >= 0"); } } for (iI = 0; iI < NUM_DIRECTION_TYPES; iI++) { pLoopPlot = plotDirection(iX, iY, ((DirectionTypes)iI)); if (pLoopPlot != NULL) { if ((pLoopPlot->getBonusType() != NO_BONUS) && (pLoopPlot->getBonusType() != eBonus)) { return false; } } } CvBonusInfo& pInfo = GC.getBonusInfo(eBonus); if (pPlot->isWater()) { if (((GC.getMapINLINE().getNumBonusesOnLand(eBonus) * 100) / (GC.getMapINLINE().getNumBonuses(eBonus) + 1)) < pInfo.getMinLandPercent()) { return false; } } // Make sure there are none of the same bonus nearby: iRange = pInfo.getUniqueRange(); for (iDX = -(iRange); iDX <= iRange; iDX++) { for (iDY = -(iRange); iDY <= iRange; iDY++) { pLoopPlot = plotXY(iX, iY, iDX, iDY); if (pLoopPlot != NULL) { if (pLoopPlot->area() == pArea) { if (plotDistance(iX, iY, pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE()) <= iRange) { if (pLoopPlot->getBonusType() == eBonus) { return false; } } } } } } return true; }
void CvMapGenerator::addRivers() { PROFILE_FUNC(); if (gDLL->getPythonIFace()->pythonAddRivers() && !gDLL->getPythonIFace()->pythonUsingDefaultImpl()) { return; // Python override } gDLL->NiTextOut("Adding Rivers..."); CvPlot* pLoopPlot; CvPlot* pStartPlot; int iPass; int iRiverSourceRange; int iSeaWaterRange; int iI; for (iPass = 0; iPass < 4; iPass++) { if (iPass <= 1) { iRiverSourceRange = GC.getXMLval(XML_RIVER_SOURCE_MIN_RIVER_RANGE); } else { iRiverSourceRange = (GC.getXMLval(XML_RIVER_SOURCE_MIN_RIVER_RANGE) / 2); } if (iPass <= 1) { iSeaWaterRange = GC.getXMLval(XML_RIVER_SOURCE_MIN_SEAWATER_RANGE); } else { iSeaWaterRange = (GC.getXMLval(XML_RIVER_SOURCE_MIN_SEAWATER_RANGE) / 2); } for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++) { gDLL->callUpdater(); pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI); FAssertMsg(pLoopPlot != NULL, "LoopPlot is not assigned a valid value"); if (!(pLoopPlot->isWater())) { if (((iPass == 0) && (pLoopPlot->isHills() || pLoopPlot->isPeak())) || ((iPass == 1) && !(pLoopPlot->isCoastalLand()) && (GC.getGameINLINE().getMapRandNum(8, "addRivers") == 0)) || ((iPass == 2) && (pLoopPlot->isHills() || pLoopPlot->isPeak()) && (pLoopPlot->area()->getNumRiverEdges() < ((pLoopPlot->area()->getNumTiles() / GC.getXMLval(XML_PLOTS_PER_RIVER_EDGE)) + 1))) || ((iPass == 3) && (pLoopPlot->area()->getNumRiverEdges() < ((pLoopPlot->area()->getNumTiles() / GC.getXMLval(XML_PLOTS_PER_RIVER_EDGE)) + 1)))) { if (!(GC.getMapINLINE().findWater(pLoopPlot, iRiverSourceRange, true))) { if (!(GC.getMapINLINE().findWater(pLoopPlot, iSeaWaterRange, false))) { pStartPlot = pLoopPlot->getInlandCorner(); if (pStartPlot != NULL) { doRiver(pStartPlot); } } } } } } } }
bool CvMapGenerator::canPlaceBonusAt(BonusTypes eBonus, int iX, int iY, bool bIgnoreLatitude) { PROFILE_FUNC(); CvArea* pArea; CvPlot* pPlot; CvPlot* pLoopPlot; int iRange; int iDX, iDY; int iI; pPlot = GC.getMapINLINE().plotINLINE(iX, iY); pArea = pPlot->area(); if (!(pPlot->canHaveBonus(eBonus, bIgnoreLatitude))) { return false; } long result = 0; CyPlot kPlot = CyPlot(pPlot); CyArgsList argsList; argsList.add(gDLL->getPythonIFace()->makePythonObject(&kPlot)); if (gDLL->getPythonIFace()->callFunction(gDLL->getPythonIFace()->getMapScriptModule(), "canPlaceBonusAt", argsList.makeFunctionArgs(), &result)) { if (!gDLL->getPythonIFace()->pythonUsingDefaultImpl()) { if (result >= 0) { return result; } else { FAssertMsg(false, "canPlaceBonusAt() must return >= 0"); } } } for (iI = 0; iI < NUM_DIRECTION_TYPES; iI++) { pLoopPlot = plotDirection(iX, iY, ((DirectionTypes)iI)); if (pLoopPlot != NULL) { if ((pLoopPlot->getBonusType() != NO_BONUS) && (pLoopPlot->getBonusType() != eBonus)) { return false; } } } CvBonusInfo& pInfo = GC.getBonusInfo(eBonus); CvBonusClassInfo& pClassInfo = GC.getBonusClassInfo((BonusClassTypes) pInfo.getBonusClassType()); if (pPlot->isWater()) { if (((GC.getMapINLINE().getNumBonusesOnLand(eBonus) * 100) / (GC.getMapINLINE().getNumBonuses(eBonus) + 1)) < pInfo.getMinLandPercent()) { return false; } } // Make sure there are no bonuses of the same class (but a different type) nearby: iRange = pClassInfo.getUniqueRange(); for (iDX = -(iRange); iDX <= iRange; iDX++) { for (iDY = -(iRange); iDY <= iRange; iDY++) { pLoopPlot = plotXY(iX, iY, iDX, iDY); if (pLoopPlot != NULL) { if (pLoopPlot->area() == pArea) { if (plotDistance(iX, iY, pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE()) <= iRange) { BonusTypes eOtherBonus = pLoopPlot->getBonusType(); if (eOtherBonus != NO_BONUS) { if (GC.getBonusInfo(eOtherBonus).getBonusClassType() == pInfo.getBonusClassType()) { return false; } } } } } } } // Make sure there are none of the same bonus nearby: iRange = pInfo.getUniqueRange(); for (iDX = -(iRange); iDX <= iRange; iDX++) { for (iDY = -(iRange); iDY <= iRange; iDY++) { pLoopPlot = plotXY(iX, iY, iDX, iDY); if (pLoopPlot != NULL) { if (pLoopPlot->area() == pArea) { if (plotDistance(iX, iY, pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE()) <= iRange) { if (pLoopPlot->getBonusType() == eBonus) { return false; } } } } } } return true; }