Hooks
static bool BeforeCvCitySiteEvaluator_PlotFoundValue(CvCitySiteEvaluator* self, CvPlot* pPlot, CvPlayer* pPlayer, YieldTypes eYield, bool arg3, int& result);static void AfterCvCitySiteEvaluator_PlotFoundValue(CvCitySiteEvaluator* self, CvPlot* pPlot, CvPlayer* pPlayer, YieldTypes eYield, bool arg3, int& result);static int ReplaceCvCitySiteEvaluator_PlotFoundValue(int (*original)(CvCitySiteEvaluator*, CvPlot*, CvPlayer*, YieldTypes, bool), CvCitySiteEvaluator* self, CvPlot* pPlot, CvPlayer* pPlayer, YieldTypes eYield, bool arg3);CivRegisterBefore<CivHooks::CvCitySiteEvaluator_PlotFoundValue>(host, &BeforeCvCitySiteEvaluator_PlotFoundValue);CivRegisterAfter<CivHooks::CvCitySiteEvaluator_PlotFoundValue>(host, &AfterCvCitySiteEvaluator_PlotFoundValue);CivRegisterReplace<CivHooks::CvCitySiteEvaluator_PlotFoundValue>(host, &ReplaceCvCitySiteEvaluator_PlotFoundValue);
Code
279/// Retrieve the relative value of this plot (including plots that would be in city radius)280int CvCitySiteEvaluator::PlotFoundValue(CvPlot* pPlot, CvPlayer* pPlayer, YieldTypes eYield, bool)281{282 CvAssert(pPlot);283 if(!pPlot)284 return 0;285286 // Make sure this player can even build a city here287 if(!CanFound(pPlot, pPlayer, false))288 {289 return 0;290 }291292 int rtnValue = 0;293294 int iFoodValue = 0;295 int iHappinessValue = 0;296 int iProductionValue = 0;297 int iGoldValue = 0;298 int iScienceValue = 0;299 int iFaithValue = 0;300 int iResourceValue = 0;301 int iStrategicValue = 0;302303 int iCelticForestCount = 0;304 int iIroquoisForestCount = 0;305 int iBrazilJungleCount = 0;306 int iNaturalWonderCount = 0;307 int iDesertCount = 0;308 int iWetlandsCount = 0;309310 int iTotalFoodValue = 0;311 int iTotalHappinessValue = 0;312 int iTotalProductionValue = 0;313 int iTotalGoldValue = 0;314 int iTotalScienceValue = 0;315 int iTotalFaithValue = 0;316 int iTotalResourceValue = 0;317 int iTotalStrategicValue = 0;318319 int iClosestCityOfMine = 999;320 int iClosestEnemyCity = 999;321322 int iCapitalArea = NULL;323324 bool bIsInca = false;325 int iAdjacentMountains = 0;326327 if ( pPlayer->getCapitalCity() )328 iCapitalArea = pPlayer->getCapitalCity()->getArea();329330 // Custom code for Inca ideal terrace farm locations331 ImprovementTypes eIncaImprovement = (ImprovementTypes)GC.getInfoTypeForString("IMPROVEMENT_TERRACE_FARM", true); 332 if(eIncaImprovement != NO_IMPROVEMENT)333 {334 CvImprovementEntry* pkEntry = GC.getImprovementInfo(eIncaImprovement);335 if(pkEntry != NULL && pkEntry->IsSpecificCivRequired())336 {337 CivilizationTypes eCiv = pkEntry->GetRequiredCivilization();338 if(eCiv == pPlayer->getCivilizationType())339 {340 bIsInca = true;341 }342 }343 }344345 for (int iDX = -7; iDX <= 7; iDX++)346 {347 for (int iDY = -7; iDY <= 7; iDY++)348 {349 CvPlot* pLoopPlot = plotXY(pPlot->getX(), pPlot->getY(), iDX, iDY);350351 if (pLoopPlot != NULL)352 {353 int iDistance = plotDistance(pPlot->getX(), pPlot->getY(), pLoopPlot->getX(), pLoopPlot->getY());354 if (iDistance <= 7)355 {356 if ((pLoopPlot->getOwner() == NO_PLAYER) || (pLoopPlot->getOwner() == pPlayer->GetID()))357 {358 // See if there are other cities nearby359 if (iClosestCityOfMine > iDistance)360 {361 if (pLoopPlot->isCity())362 {363 iClosestCityOfMine = iDistance;364 }365 }366367 // Skip the city plot itself for now368 if (iDistance <= 5)369 {370 int iRingModifier = m_iRingModifier[iDistance];371372 iFoodValue = 0;373 iProductionValue = 0;374 iGoldValue = 0;375 iScienceValue = 0;376 iHappinessValue = 0;377 iResourceValue = 0;378 iStrategicValue = 0;379380#if defined(MOD_GLOBAL_CITY_WORKING)381 if (iDistance > 0 && iDistance <= pPlayer->getWorkPlotDistance())382#else 383 if (iDistance > 0 && iDistance <= NUM_CITY_RINGS)384#endif385 {386 if (eYield == NO_YIELD || eYield == YIELD_FOOD)387 {388 iFoodValue = iRingModifier * ComputeFoodValue(pLoopPlot, pPlayer) * /*15*/ GC.getSETTLER_FOOD_MULTIPLIER();389 }390 if (eYield == NO_YIELD || eYield == YIELD_PRODUCTION)391 {392 iProductionValue = iRingModifier * ComputeProductionValue(pLoopPlot, pPlayer) * /*3*/ GC.getSETTLER_PRODUCTION_MULTIPLIER();393 }394 if (eYield == NO_YIELD || eYield == YIELD_GOLD)395 {396 iGoldValue = iRingModifier * ComputeGoldValue(pLoopPlot, pPlayer) * /*2*/ GC.getSETTLER_GOLD_MULTIPLIER();397 }398 if (eYield == NO_YIELD || eYield == YIELD_SCIENCE)399 {400 iScienceValue = iRingModifier * ComputeScienceValue(pLoopPlot, pPlayer) * /*1*/ GC.getSETTLER_SCIENCE_MULTIPLIER();401 }402 if (eYield == NO_YIELD || eYield == YIELD_FAITH)403 {404 iFaithValue = iRingModifier * ComputeFaithValue(pLoopPlot, pPlayer) * /*1*/ GC.getSETTLER_FAITH_MULTIPLIER();405 }406#if defined(MOD_API_UNIFIED_YIELDS)407 // We don't flavour settle site choice by tourism - way to early for that!!!408#endif409 }410411 // whether or not we are working these we get the benefit as long as culture can grow to take them412 if (iDistance <= 5 && pLoopPlot->getOwner() == NO_PLAYER) // there is no benefit if we already own these tiles413 {414 iHappinessValue = iRingModifier * ComputeHappinessValue(pLoopPlot, pPlayer) * /*6*/ GC.getSETTLER_HAPPINESS_MULTIPLIER();415 iResourceValue = iRingModifier * ComputeTradeableResourceValue(pLoopPlot, pPlayer) * /*1*/ GC.getSETTLER_RESOURCE_MULTIPLIER();416 if (iDistance)417 iStrategicValue = ComputeStrategicValue(pLoopPlot, pPlayer, iDistance) * /*1*/ GC.getSETTLER_STRATEGIC_MULTIPLIER(); // the ring is included in the computation418 }419420 iTotalFoodValue += iFoodValue;421 iTotalHappinessValue += iHappinessValue;422 iTotalProductionValue += iProductionValue;423 iTotalGoldValue += iGoldValue;424 iTotalScienceValue += iScienceValue;425 iTotalFaithValue += iFaithValue;426 iTotalResourceValue += iResourceValue;427 iTotalStrategicValue += iStrategicValue;428429 int iPlotValue = iFoodValue + iHappinessValue + iProductionValue + iGoldValue + iScienceValue + iFaithValue + iResourceValue;430 431 if (iPlotValue == 0)432 {433 // this tile is so bad it gets negatives434 iPlotValue -= iRingModifier * GC.getSETTLER_FOOD_MULTIPLIER() * 2;435 }436 iPlotValue += iStrategicValue;437438 // if this tile is a NW boost the value just so that we force the AI to claim them (if we can work it)439#if defined(MOD_GLOBAL_CITY_WORKING)440 if (pLoopPlot->IsNaturalWonder() && iDistance > 0 && iDistance <= pPlayer->getWorkPlotDistance())441#else 442 if (pLoopPlot->IsNaturalWonder() && iDistance > 0 && iDistance <= NUM_CITY_RINGS)443#endif444 {445 //iPlotValue += iPlotValue * 2 + 10;446 iPlotValue += iPlotValue * 2 + 500;447 }448449 // lower value a lot if we already own this tile450 if (iPlotValue > 0 && pLoopPlot->getOwner() == pPlayer->GetID())451 {452 iPlotValue /= 4;453 }454455 // add this plot into the total456 rtnValue += iPlotValue;457458 FeatureTypes ePlotFeature = pLoopPlot->getFeatureType();459 ImprovementTypes ePlotImprovement = pLoopPlot->getImprovementType();460 ResourceTypes ePlotResource = pLoopPlot->getResourceType();461462 if (ePlotFeature == FEATURE_FOREST)463 {464 if (iDistance <= 5)465 {466 ++iIroquoisForestCount;467 if (iDistance == 1)468 {469 if (ePlotImprovement == NO_IMPROVEMENT)470 {471 ++iCelticForestCount;472 }473 }474 }475 }476 else if (ePlotFeature == FEATURE_JUNGLE)477 {478#if defined(MOD_GLOBAL_CITY_WORKING)479 if (iDistance <= pPlayer->getWorkPlotDistance())480#else 481 if (iDistance <= NUM_CITY_RINGS)482#endif483 {484 ++iBrazilJungleCount;485 }486 }487 else if (ePlotFeature == FEATURE_MARSH || ePlotFeature == FEATURE_FLOOD_PLAINS)488 {489#if defined(MOD_GLOBAL_CITY_WORKING)490 if (iDistance <= pPlayer->getWorkPlotDistance())491#else 492 if (iDistance <= NUM_CITY_RINGS)493#endif494 {495 ++iWetlandsCount;496 }497 }498499 if (pLoopPlot->IsNaturalWonder())500 {501 if (iDistance <= 1)502 {503 ++iNaturalWonderCount;504 }505 }506507 if (pLoopPlot->getTerrainType() == TERRAIN_DESERT)508 {509#if defined(MOD_GLOBAL_CITY_WORKING)510 if (iDistance <= pPlayer->getWorkPlotDistance())511#else 512 if (iDistance <= NUM_CITY_RINGS)513#endif514 {515 if (ePlotResource == NO_RESOURCE)516 {517 ++iDesertCount;518 }519 }520 }521522 if (bIsInca)523 {524 if (pLoopPlot->isHills())525 {526#if defined(MOD_GLOBAL_CITY_WORKING)527 if (iDistance <= pPlayer->getWorkPlotDistance())528#else 529 if (iDistance <= NUM_CITY_RINGS)530#endif531 {532 iAdjacentMountains = pLoopPlot->GetNumAdjacentMountains();533 if (iAdjacentMountains > 0 && iAdjacentMountains < 6)534 {535 //give the bonus if it's hills, with additional if bordered by mountains536 rtnValue += m_iIncaMultiplier + (iAdjacentMountains * m_iIncaMultiplier);537 }538 }539 540 }541 }542 }543 }544 else // this tile is owned by someone else545 {546 // See if there are other cities nearby (only count major civs)547 if (iClosestEnemyCity > iDistance)548 {549 if (pLoopPlot->isCity() && (pLoopPlot->getOwner() < MAX_MAJOR_CIVS))550 {551 iClosestEnemyCity = iDistance;552 }553 }554 }555 }556 }557 }558 }559560 if (pPlayer->GetPlayerTraits()->IsFaithFromUnimprovedForest())561 {562 if (iCelticForestCount >= 3)563 {564 rtnValue += 2 * 1000 * m_iFlavorMultiplier[YIELD_FAITH];565 }566 else if (iCelticForestCount >= 1)567 {568 rtnValue += 1 * 1000 * m_iFlavorMultiplier[YIELD_FAITH];569 }570 }571 else if (pPlayer->GetPlayerTraits()->IsMoveFriendlyWoodsAsRoad())572 {573 rtnValue += iIroquoisForestCount * 10; 574 }575 else if (pPlayer->GetPlayerTraits()->GetNaturalWonderYieldModifier() > 0) //ie: Spain576 {577 rtnValue += iNaturalWonderCount * m_iSpainMultiplier; 578 }579580 // Custom code for Brazil581 ImprovementTypes eBrazilImprovement = (ImprovementTypes)GC.getInfoTypeForString("IMPROVEMENT_BRAZILWOOD_CAMP", true); 582 if(eBrazilImprovement != NO_IMPROVEMENT)583 {584 CvImprovementEntry* pkEntry = GC.getImprovementInfo(eBrazilImprovement);585 if(pkEntry != NULL && pkEntry->IsSpecificCivRequired())586 {587 CivilizationTypes eCiv = pkEntry->GetRequiredCivilization();588 if(eCiv == pPlayer->getCivilizationType())589 {590 rtnValue += iBrazilJungleCount * m_iBrazilMultiplier;591 }592 }593 }594595 // Custom code for Morocco596 ImprovementTypes eMoroccoImprovement = (ImprovementTypes)GC.getInfoTypeForString("IMPROVEMENT_KASBAH", true); 597 if(eMoroccoImprovement != NO_IMPROVEMENT)598 {599 CvImprovementEntry* pkEntry = GC.getImprovementInfo(eMoroccoImprovement);600 if(pkEntry != NULL && pkEntry->IsSpecificCivRequired())601 {602 CivilizationTypes eCiv = pkEntry->GetRequiredCivilization();603 if(eCiv == pPlayer->getCivilizationType())604 {605 rtnValue += iDesertCount * m_iMorrocoMultiplier;606 }607 }608 }609610 //Custom code for Netherlands611 ImprovementTypes ePolderImprovement = (ImprovementTypes)GC.getInfoTypeForString("IMPROVEMENT_POLDER", true); 612 if(ePolderImprovement != NO_IMPROVEMENT)613 {614 CvImprovementEntry* pkEntry = GC.getImprovementInfo(ePolderImprovement);615 if(pkEntry != NULL && pkEntry->IsSpecificCivRequired())616 {617 CivilizationTypes eCiv = pkEntry->GetRequiredCivilization();618 if(eCiv == pPlayer->getCivilizationType())619 {620 rtnValue += iWetlandsCount * m_iNetherlandsMultiplier;621 }622 }623 }624625 if (rtnValue < 0) rtnValue = 0;626627 // Finally, look at the city plot itself and use it as an overall multiplier628 if (pPlot->getResourceType(pPlayer->getTeam()) != NO_RESOURCE)629 {630 rtnValue += (int)rtnValue * /*-50*/ GC.getBUILD_ON_RESOURCE_PERCENT() / 100;631 }632633 if (pPlot->isRiver())634 {635 rtnValue += (int)rtnValue * /*15*/ GC.getBUILD_ON_RIVER_PERCENT() / 100;636 }637638 if (pPlot->isCoastalLand(GC.getMIN_WATER_SIZE_FOR_OCEAN()))639 {640 // okay, coast used to have lots of gold so players settled there "naturally", it doesn't any more, so I am going to give it a nudge in that direction641 // slewis - removed Brian(?)'s rtnValue adjustment and raised the BUILD_ON_COAST_PERCENT to 40 from 25642 //rtnValue += rtnValue > 0 ? 10 : 0;643 rtnValue += (int)rtnValue * /*40*/ GC.getSETTLER_BUILD_ON_COAST_PERCENT() / 100;644 int iNavalFlavor = pPlayer->GetGrandStrategyAI()->GetPersonalityAndGrandStrategy((FlavorTypes)m_iNavalIndex);645 if (iNavalFlavor > 7)646 {647 rtnValue += (int)rtnValue * /*40*/ GC.getSETTLER_BUILD_ON_COAST_PERCENT() / 100;648 }649 if (pPlayer->getCivilizationInfo().isCoastalCiv()) // we really like the coast (England, Norway, Polynesia, Carthage, etc.)650 {651 rtnValue += rtnValue > 0 ? 25 : 0;652 rtnValue *= 2;653 }654 }655656 // Nearby Cities?657658 // Human659 if (pPlayer != NULL && pPlayer->isHuman())660 {661 if (iClosestCityOfMine == 3)662 {663 rtnValue /= 2;664 }665 }666 // AI667 else668 {669 int iGrowthFlavor = pPlayer->GetGrandStrategyAI()->GetPersonalityAndGrandStrategy((FlavorTypes)m_iGrowthIndex);670 int iExpansionFlavor = pPlayer->GetGrandStrategyAI()->GetPersonalityAndGrandStrategy((FlavorTypes)m_iExpansionIndex);671672 int iSweetSpot = 5;673 iSweetSpot += (iGrowthFlavor > 7) ? 1 : 0;674 iSweetSpot += (iExpansionFlavor > 7) ? -1 : 0;675 iSweetSpot += (iGrowthFlavor < 4) ? -1 : 0;676 iSweetSpot += (iExpansionFlavor < 4) ? 1 : 0;677 iSweetSpot = max(4,iSweetSpot);678 iSweetSpot = min(6,iSweetSpot);679680 if (iClosestCityOfMine == iSweetSpot) 681 {682 // 1.5 was not enough 2.0 was too much, so lets split the difference683 rtnValue *= 175;684 rtnValue /= 100;685 }686 else if (iClosestCityOfMine < iSweetSpot)687 {688 rtnValue /= 2;689 }690 else if (iClosestCityOfMine > 7)691 {692 rtnValue *= 2;693 rtnValue /= 3;694 }695696 // use boldness to decide if we want to push close to enemies697 int iBoldness = pPlayer->GetDiplomacyAI()->GetBoldness();698 if (iBoldness < 4)699 {700 if (iClosestEnemyCity <= 4)701 {702 rtnValue /= 4;703 }704 else if (iClosestEnemyCity == 5)705 {706 rtnValue /= 2;707 }708 }709 else if (iBoldness > 7)710 {711 if (iClosestEnemyCity <= 5 && iClosestCityOfMine < 8)712 {713 rtnValue *= 3;714 rtnValue /= 2;715 }716 }717 else718 {719 if (iClosestEnemyCity < 5)720 {721 rtnValue *= 2;722 rtnValue /= 3;723 }724 }725726 // if we are offshore, pull cities in tighter727 if (iCapitalArea != pPlot->getArea())728 {729 if (iClosestCityOfMine < 7)730 {731 rtnValue *= 3;732 rtnValue /= 2;733 }734 }735 }736737 rtnValue = (rtnValue > 0) ? rtnValue : 0;738739 return rtnValue;740}