Hooks
static bool BeforeCityStrategyAIHelpers_IsTestCityStrategy_WantTileImprovers(AICityStrategyTypes eStrategy, CvCity* pCity, bool& result);static void AfterCityStrategyAIHelpers_IsTestCityStrategy_WantTileImprovers(AICityStrategyTypes eStrategy, CvCity* pCity, bool& result);static bool ReplaceCityStrategyAIHelpers_IsTestCityStrategy_WantTileImprovers(bool (*original)(AICityStrategyTypes, CvCity*), AICityStrategyTypes eStrategy, CvCity* pCity);CivRegisterBefore<CivHooks::CityStrategyAIHelpers_IsTestCityStrategy_WantTileImprovers>(host, &BeforeCityStrategyAIHelpers_IsTestCityStrategy_WantTileImprovers);CivRegisterAfter<CivHooks::CityStrategyAIHelpers_IsTestCityStrategy_WantTileImprovers>(host, &AfterCityStrategyAIHelpers_IsTestCityStrategy_WantTileImprovers);CivRegisterReplace<CivHooks::CityStrategyAIHelpers_IsTestCityStrategy_WantTileImprovers>(host, &ReplaceCityStrategyAIHelpers_IsTestCityStrategy_WantTileImprovers);
Code
2421/// "Want Tile Improvers" City Strategy: Looks at how many Builders are available empire-wide. This is not a Player Strategy because it's only worried about training new Builders in Cities, and not Techs, Policies, etc.2422bool CityStrategyAIHelpers::IsTestCityStrategy_WantTileImprovers(AICityStrategyTypes eStrategy, CvCity* pCity)2423{2424 CvPlayer& kPlayer = GET_PLAYER(pCity->getOwner());2425 int iLastTurnWorkerDisbanded = kPlayer.GetEconomicAI()->GetLastTurnWorkerDisbanded();2426 if(iLastTurnWorkerDisbanded >= 0 && GC.getGame().getGameTurn() - iLastTurnWorkerDisbanded <= 10)2427 {2428 return false;2429 }24302431 if(!GET_PLAYER(pCity->getOwner()).isMinorCiv())2432 {2433 // If we're losing at war, return false2434 if(GET_PLAYER(pCity->getOwner()).GetDiplomacyAI()->GetStateAllWars() == STATE_ALL_WARS_LOSING)2435 return false;2436 }24372438 int iNumWorkers = kPlayer.GetNumUnitsWithUnitAI(UNITAI_WORKER, true, false);2439 if(iNumWorkers >= ((kPlayer.getNumCities() * 3) / 2) + 1)2440 return false;24412442 // If we're under attack from Barbs and have 1 or fewer cities then training more Workers will only hurt us2443 //if (kPlayer.getNumCities() <= 1)2444 //{2445 // MilitaryAIStrategyTypes eStrategyKillBarbs = (MilitaryAIStrategyTypes) GC.getInfoTypeForString("MILITARYAISTRATEGY_ERADICATE_BARBARIANS");2446 // if (eStrategyKillBarbs != NO_MILITARYAISTRATEGY)2447 // {2448 // if (GET_PLAYER(pCity->getOwner()).GetMilitaryAI()->IsUsingStrategy(eStrategyKillBarbs))2449 // return false;2450 // }2451 //}24522453 // Don't get desperate for training a Builder here unless the City is at least of a certain size2454 if(pCity->getPopulation() >= /*2*/ GC.getAI_CITYSTRATEGY_WANT_TILE_IMPROVERS_MINIMUM_SIZE())2455 {2456 int iNumBuilders = kPlayer.GetNumUnitsWithUnitAI(UNITAI_WORKER, true, false);24572458 // If we don't even have 1 builder on map or in a queue, turn this on immediately2459 if(iNumBuilders < 1)2460 {2461 return true;2462 }24632464 CvAICityStrategyEntry* pCityStrategy = pCity->GetCityStrategyAI()->GetAICityStrategies()->GetEntry(eStrategy);24652466 int iWeightThresholdModifier = CityStrategyAIHelpers::GetWeightThresholdModifier(eStrategy, pCity); // 2 Extra Weight per TILE_IMPROVEMENT Flavor2467 int iPerCityThreshold = pCityStrategy->GetWeightThreshold() + iWeightThresholdModifier; // 4024682469 // Look at all Tiles this City could potentially work to see if there are any Water Resources that could be improved2470 CvPlot* pLoopPlot;2471 int iNumResources = 0;2472 int iNumImprovedResources = 0;24732474#if defined(MOD_GLOBAL_CITY_WORKING)2475 for(int iPlotLoop = 0; iPlotLoop < pCity->GetNumWorkablePlots(); iPlotLoop++)2476#else2477 for(int iPlotLoop = 0; iPlotLoop < NUM_CITY_PLOTS; iPlotLoop++)2478#endif2479 {2480 pLoopPlot = plotCity(pCity->getX(), pCity->getY(), iPlotLoop);24812482 if(pLoopPlot != NULL)2483 {2484 if(pLoopPlot->getOwner() == pCity->getOwner())2485 {2486 if(!pLoopPlot->isWater())2487 {2488 ResourceTypes eResource = pLoopPlot->getResourceType(kPlayer.getTeam());2489 if(eResource == NO_RESOURCE)2490 {2491 continue;2492 }24932494 // loop through the build types to find one that we can use2495 ImprovementTypes eCorrectImprovement = NO_IMPROVEMENT;2496 BuildTypes eCorrectBuild = NO_BUILD;2497 int iBuildIndex;2498 for(iBuildIndex = 0; iBuildIndex < GC.getNumBuildInfos(); iBuildIndex++)2499 {2500 const BuildTypes eBuild = static_cast<BuildTypes>(iBuildIndex);2501 CvBuildInfo* pkBuildInfo = GC.getBuildInfo(eBuild);2502 if(pkBuildInfo)2503 {2504 const ImprovementTypes eImprovement = (ImprovementTypes)pkBuildInfo->getImprovement();25052506 // if this is the improvement we're looking for2507 if(eImprovement != NO_IMPROVEMENT)2508 {2509 CvImprovementEntry* pkImprovementInfo = GC.getImprovementInfo(eImprovement);2510 if(pkImprovementInfo)2511 {2512 if(pkImprovementInfo->IsImprovementResourceTrade(eResource))2513 {2514 eCorrectBuild = eBuild;2515 eCorrectImprovement = eImprovement;2516 break;2517 }2518 }2519 }2520 }25212522 }25232524 // no valid build found2525 if(eCorrectBuild == NO_BUILD || eCorrectImprovement == NO_IMPROVEMENT)2526 {2527 continue;2528 }252925302531 // if we can't build the improvement for the resource, continue!2532 if(!kPlayer.canBuild(pLoopPlot, eCorrectBuild, false, false))2533 {2534 if(pLoopPlot->getImprovementType() == eCorrectImprovement)2535 {2536 iNumImprovedResources++;2537 iNumResources++;2538 }25392540 continue;2541 }25422543 iNumResources++;2544 }2545 }2546 }2547 }25482549 bool bManyUnimproveResources = (2 * (iNumResources - iNumImprovedResources)) > iNumResources;2550 int iMultiplier = kPlayer.getNumCities();2551 iMultiplier += kPlayer.countCitiesFeatureSurrounded();2552 if(bManyUnimproveResources)2553 iMultiplier += 1;25542555 int iNumSettlers = kPlayer.GetNumUnitsWithUnitAI(UNITAI_SETTLE, true, false);2556 iMultiplier += iNumSettlers;25572558 int iWeightThreshold = (iPerCityThreshold * iMultiplier);25592560 //Do we want more Builders?2561 if((iNumBuilders * 100) < iWeightThreshold)2562 {2563 // slewis - need to check to see if training another worker will put us below the -10 threshold.2564 // slewis - todo: move -10 to a xml value2565 return (kPlayer.calculateGoldRate() > -10);25662567 // Also want to check and see if we have enough happiness to support another builder2568 //int iBuilderUnhappiness = 0;2569 //int iBuildersInGame = kPlayer.GetNumUnitsWithUnitAI(UNITAI_WORKER, false, false);2570 //if (iBuildersInGame > 0)2571 //{2572 // CvUnit *pLoopUnit;2573 // int iLoop;2574 // for (pLoopUnit = kPlayer.firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = kPlayer.nextUnit(&iLoop))2575 // {2576 // if (pLoopUnit->AI_getUnitAIType() == UNITAI_WORKER)2577 // {2578 // break;2579 // }2580 // }2581 // if (pLoopUnit)2582 // {2583 // iBuilderUnhappiness = pLoopUnit->getUnitInfo().GetUnhappiness();2584 // }2585 //}25862587 //return (kPlayer.GetExcessHappiness()) >= (iNumBuilders - iBuildersInGame + 1) * iBuilderUnhappiness;2588 }2589 }25902591 return false;2592}