Single Player bugs and crashes v36 plus (SVN) - After the 24th of October 2015

Status
Not open for further replies.
Part IV
Spoiler :
Code:
	m_iTempBuildPriority--;

	if ((getDomainFreeExperience(DOMAIN_LAND) == 0) && (getYieldRate(YIELD_PRODUCTION) > 4))
	{
    	if (AI_chooseBuilding(BUILDINGFOCUS_EXPERIENCE, (kPlayer.getCurrentEra() > 1) ? 0 : 7, 33))
		{
			if( gCityLogLevel >= 2 ) logBBAI("      City %S uses special BUILDINGFOCUS_EXPERIENCE 1", getName().GetCString());
			return;
		}
	}

	m_iTempBuildPriority--;

	//	Koshling - increased priority for economic builds, especially in early game and allowed
	//	wonders in if they appear best
	if (AI_chooseBuilding(iEconomyFlags | BUILDINGFOCUS_WONDEROK, 20, 0, kPlayer.getCurrentEra() == 0 ? 100 : 50))
	{
		if( gCityLogLevel >= 2 ) logBBAI("      City %S uses choose iEconomyFlags (Koshling)", getName().GetCString());
		return;
	}

	m_iTempBuildPriority--;

//TB Build Mod (Moved up in priority)
#ifdef C2C_BUILD
	if (!bAlwaysPeace )
	{
		PROFILE("AI_chooseProduction.NotAlwaysPeace");

		if (AI_chooseBuilding(BUILDINGFOCUS_DEFENSE, 20, 0, bDanger ? -1 : 3*getPopulation()))
		{
			return;
		}
		
		if (AI_chooseBuilding(BUILDINGFOCUS_EXPERIENCE, 20, 0, (bDanger ? 10 : 4)*std::min(9,getPopulation())))
        {
            return;
	    }
	}
#endif
//TB Build Mod end	

	m_iTempBuildPriority--;

	// Koshling in early game moved optional non-wartime attack unit builds below economy
	// don't build frivolous things if this is an important city unless we at war
    if (!bInhibitUnits && (!bImportantCity || bLandWar || bAssault) && kPlayer.getCurrentEra() == 0)
    {
        if (bPrimaryArea)
        {
            if (kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_ATTACK) == 0)
            {
                if (AI_chooseUnit("primary area attack", UNITAI_ATTACK))
                {
                    return;
                }
            }
        }
	}

	m_iTempBuildPriority--;

	//	Koshling - next section moved from quite a bit earlier to avoid not-needed-yet worker builds
	//	before we have checked basic economy builds
	//do a check for one tile island type thing?
    //this can be overridden by "wait and grow more"
    if (!bInhibitUnits && !bDanger && (iExistingWorkers == 0) && (isCapital() || (iNeededWorkers > 0) || (iNeededSeaWorkers > iExistingSeaWorkers)))
    {
		if( !(bDefenseWar && iWarSuccessRatio < -30) && !(kPlayer.AI_isDoStrategy(AI_STRATEGY_TURTLE)) )
		{
			if ((AI_countNumBonuses(NO_BONUS, /*bIncludeOurs*/ true, /*bIncludeNeutral*/ true, -1, /*bLand*/ true, /*bWater*/ false) > 0) || 
				(isCapital() && (getPopulation() > 3) && iNumCitiesInArea > 1))
    		{
				if (!bChooseWorker && AI_chooseUnit("optional worker", UNITAI_WORKER))
				{
					return;
				}
				bChooseWorker = true;
    		}

			if (iNeededSeaWorkers > iExistingSeaWorkers)
			{
				if (AI_chooseUnit("optional sea worker", UNITAI_WORKER_SEA))
				{
					return;
				}
			}
		}
    }
	
	m_iTempBuildPriority--;

	int iMaxUnitSpending = (bAggressiveAI ? 6 : 3) + iBuildUnitProb / 3;

	if( kPlayer.AI_isDoVictoryStrategy(AI_VICTORY_CONQUEST4) )
	{
		iMaxUnitSpending += 7;
	}
	else if( kPlayer.AI_isDoVictoryStrategy(AI_VICTORY_CONQUEST3) || kPlayer.AI_isDoVictoryStrategy(AI_VICTORY_DOMINATION3) )
	{
		iMaxUnitSpending += 3;
	}
	else if( kPlayer.AI_isDoVictoryStrategy(AI_VICTORY_CONQUEST1) )
	{
		iMaxUnitSpending += 1;
	}

    if (bAlwaysPeace)
	{
		iMaxUnitSpending = -10;
	}
    else if (kPlayer.AI_isDoStrategy(AI_STRATEGY_FINAL_WAR))
    {
    	iMaxUnitSpending = 5 + iMaxUnitSpending + (100 - iMaxUnitSpending) / 2;
    }
    else
    {
    	iMaxUnitSpending += bDefenseWar ? 4 : 0;
    	switch (pArea->getAreaAIType(getTeam()))
    	{
			case AREAAI_OFFENSIVE:
				iMaxUnitSpending += 5;
				break;
			
			case AREAAI_DEFENSIVE:
				iMaxUnitSpending += 10;
				break;
			
			case AREAAI_MASSING:
				iMaxUnitSpending += 25;
				break;
			
			case AREAAI_ASSAULT:
				iMaxUnitSpending += 8;
				break;
				
			case AREAAI_ASSAULT_MASSING:
				iMaxUnitSpending += 16;
				break;
			
			case AREAAI_ASSAULT_ASSIST:
				iMaxUnitSpending += 6;
				break;
			
			case AREAAI_NEUTRAL:
				break;
			default:
				FAssert(false);
		}
	}

	int iCarriers = kPlayer.AI_totalUnitAIs(UNITAI_CARRIER_SEA);
	
	//Afforess moved AI Aircraft logic up, Aircraft >> Sea transports
	UnitTypeWeightArray airUnitTypes;

    int iAircraftNeed = 0;
    int iAircraftHave = 0;
    UnitTypes eBestAttackAircraft = NO_UNIT;
    UnitTypes eBestMissile = NO_UNIT;
    
	if (!bInhibitUnits && iUnitCostPercentage < (iMaxUnitSpending + 4) && (!bImportantCity || bDefenseWar) )
	{
		if( bLandWar || bAssault || (iFreeAirExperience > 0) || (getCitySorenRandNum(3, "AI train air") == 0) )
		{
			int iBestAirValue = kPlayer.AI_bestCityUnitAIValue(UNITAI_ATTACK_AIR, this, &eBestAttackAircraft);
			int iBestMissileValue = kPlayer.AI_bestCityUnitAIValue(UNITAI_MISSILE_AIR, this, &eBestMissile);
			if ((iBestAirValue + iBestMissileValue) > 0)
			{
				iAircraftHave = kPlayer.AI_totalUnitAIs(UNITAI_ATTACK_AIR) + kPlayer.AI_totalUnitAIs(UNITAI_DEFENSE_AIR) + kPlayer.AI_totalUnitAIs(UNITAI_MISSILE_AIR);
				if (NO_UNIT != eBestAttackAircraft)
				{
					iAircraftNeed = (2 + kPlayer.getNumCities() * (3 * GC.getUnitInfo(eBestAttackAircraft).getAirCombat())) / (2 * std::max(1, GC.getGame().getBestLandUnitCombat()));
					int iBestDefenseValue = kPlayer.AI_bestCityUnitAIValue(UNITAI_DEFENSE_AIR, this);
					if ((iBestDefenseValue > 0) && (iBestAirValue > iBestDefenseValue))
					{
						iAircraftNeed *= 3;
						iAircraftNeed /= 2;
					}
				}
				if (iBestMissileValue > 0)
				{
					iAircraftNeed = std::max(iAircraftNeed, 1 + kPlayer.getNumCities() / 2);
				}
				
				bool bAirBlitz = kPlayer.AI_isDoStrategy(AI_STRATEGY_AIR_BLITZ);
				bool bLandBlitz = kPlayer.AI_isDoStrategy(AI_STRATEGY_LAND_BLITZ);
				if (bAirBlitz)
				{
					iAircraftNeed *= 3;
					iAircraftNeed /= 2;
				}
				else if (bLandBlitz)
				{
					iAircraftNeed /= 2;
					iAircraftNeed += 1;
				}
				
				airUnitTypes.push_back(std::make_pair(UNITAI_ATTACK_AIR, bAirBlitz ? 125 : 80));
				airUnitTypes.push_back(std::make_pair(UNITAI_DEFENSE_AIR, bLandBlitz ? 100 : 100));
				if (iBestMissileValue > 0)
				{
					airUnitTypes.push_back(std::make_pair(UNITAI_MISSILE_AIR, bAssault ? 60 : 40));
				}
				
				airUnitTypes.push_back(std::make_pair(UNITAI_ICBM, 20));
				
				if (iAircraftHave * 2 < iAircraftNeed)
				{
					if (AI_chooseLeastRepresentedUnit("need airforce", airUnitTypes))
					{
						return;
					}
				}
				// Additional check for air defenses
				int iFightersHave = kPlayer.AI_totalUnitAIs(UNITAI_DEFENSE_AIR);

				if( 3*iFightersHave < iAircraftNeed )
				{
					if (AI_chooseUnit("need air defense", UNITAI_DEFENSE_AIR))
					{
						return;
					}
				}
			}
		}
	}

	m_iTempBuildPriority--;

	// Revamped logic for production for invasions
    if (!bInhibitUnits && iUnitCostPercentage < (iMaxUnitSpending + 10))
	{
		bool bBuildAssault = bAssault;
		CvArea* pAssaultWaterArea = NULL;
		if (NULL != pWaterArea)
		{
			// Coastal city extra logic

			pAssaultWaterArea = pWaterArea;

			// If on offensive and can't reach enemy cities from here, act like using AREAAI_ASSAULT
			if( (pAssaultWaterArea != NULL) && !bBuildAssault )
			{
				if( (GET_TEAM(getTeam()).getAnyWarPlanCount(true) > 0) )
				{
					if( (pArea->getAreaAIType(getTeam()) != AREAAI_DEFENSIVE) )
					{
						// BBAI TODO: faster to switch to checking path for some selection group?
						if( !(plot()->isHasPathToEnemyCity(getTeam())) )
						{
							bBuildAssault = true;
						}
					}
				}
			}
		}

		if( bBuildAssault )
		{
			if( gCityLogLevel >= 2 ) logBBAI("      City %S uses build assault", getName().GetCString());

			UnitTypes eBestAssaultUnit = NO_UNIT; 
			if (NULL != pAssaultWaterArea)
			{
				kPlayer.AI_bestCityUnitAIValue(UNITAI_ASSAULT_SEA, this, &eBestAssaultUnit);
			}
			else
			{
				kPlayer.AI_bestCityUnitAIValue(UNITAI_ASSAULT_SEA, NULL, &eBestAssaultUnit);
			}
			
			int iBestSeaAssaultCapacity = 0;
			if (eBestAssaultUnit != NO_UNIT)
			{
				iBestSeaAssaultCapacity = GC.getUnitInfo(eBestAssaultUnit).getCargoSpace();
			}

			int iAreaAttackCityUnits = kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_ATTACK_CITY);
			
			int iUnitsToTransport = iAreaAttackCityUnits;
			iUnitsToTransport += kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_ATTACK);
			iUnitsToTransport += kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_COUNTER)/2;

			int iLocalTransports = kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_ASSAULT_SEA);
			int iTransportsAtSea = 0;
			if (NULL != pAssaultWaterArea)
			{
				iTransportsAtSea = kPlayer.AI_totalAreaUnitAIs(pAssaultWaterArea, UNITAI_ASSAULT_SEA);
			}
			else
			{
				iTransportsAtSea = kPlayer.AI_totalUnitAIs(UNITAI_ASSAULT_SEA)/2;
			}

			//The way of calculating numbers is a bit fuzzy since the ships
			//can make return trips. When massing for a war it'll train enough
			//ships to move it's entire army. Once the war is underway it'll stop
			//training so many ships on the assumption that those out at sea
			//will return...

			int iTransports = iLocalTransports + (bPrimaryArea ? iTransportsAtSea : iTransportsAtSea/4);
			int iTransportCapacity = iBestSeaAssaultCapacity*(iTransports);

			if (NULL != pAssaultWaterArea)
			{
				int iEscorts = kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_ESCORT_SEA);
				iEscorts += kPlayer.AI_totalAreaUnitAIs(pAssaultWaterArea, UNITAI_ESCORT_SEA);

				int iTransportViability = kPlayer.AI_calculateUnitAIViability(UNITAI_ASSAULT_SEA, DOMAIN_SEA);

				int iDesiredEscorts = ((1 + 2 * iTransports) / 3);
				if( iTransportViability > 95 )
				{
					// Transports are stronger than escorts (usually Galleons and Caravels)
					iDesiredEscorts /= 3;
				}
				
				if ((iEscorts < iDesiredEscorts))
				{
					if ( AI_chooseBuilding(BUILDINGFOCUS_DOMAINSEA, 12) )
					{
						return;
					}

					if (AI_chooseUnit("sea escort", UNITAI_ESCORT_SEA, (iEscorts < iDesiredEscorts/3) ? -1 : 50))
					{
						return;
					}
				}
			
				UnitTypes eBestAttackSeaUnit = NO_UNIT;  
				kPlayer.AI_bestCityUnitAIValue(UNITAI_ATTACK_SEA, this, &eBestAttackSeaUnit);
				if (eBestAttackSeaUnit != NO_UNIT)
				{
					int iDivisor = 2;
					if (GC.getUnitInfo(eBestAttackSeaUnit).getBombardRate() == 0)
					{
						iDivisor = 5;
					}

					int iAttackSea = kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_ATTACK_SEA);
					iAttackSea += kPlayer.AI_totalAreaUnitAIs(pAssaultWaterArea, UNITAI_ATTACK_SEA);
						
					if ((iAttackSea < ((1 + 2 * iTransports) / iDivisor)))
					{
						if ( AI_chooseBuilding(BUILDINGFOCUS_DOMAINSEA, 12) )
						{
							return;
						}

						if (AI_chooseUnit("sea attack", UNITAI_ATTACK_SEA, (iUnitCostPercentage < iMaxUnitSpending) ? 50 : 20))
						{
							return;
						}
					}
				}
				
				if (iUnitsToTransport > iTransportCapacity)
				{
					if ((iUnitCostPercentage < iMaxUnitSpending) || (iUnitsToTransport > 2*iTransportCapacity))
					{
						if ( AI_chooseBuilding(BUILDINGFOCUS_DOMAINSEA, 12) )
						{
							return;
						}

						if (AI_chooseUnit("sea assault", UNITAI_ASSAULT_SEA))
						{
							return;
						}
					}
				}
			}

			if (iUnitCostPercentage < iMaxUnitSpending)
			{
				if (NULL != pAssaultWaterArea)
				{
					if (!bFinancialTrouble && iCarriers < (kPlayer.AI_totalUnitAIs(UNITAI_ASSAULT_SEA) / 4))
					{
						// Reduce chances of starting if city has low production
						if ( iProductionRank > (kPlayer.getNumCities() / 3) && getCitySorenRandNum(100, "AI train carrier") < 30 )
						{
							if ( AI_chooseBuilding(BUILDINGFOCUS_DOMAINSEA, 12) )
							{
								return;
							}

							if (AI_chooseUnit("need carrier", UNITAI_CARRIER_SEA) )
							{
								return;
							}
						}
					}
				}
			}

			// Consider building more land units to invade with
			int iTrainInvaderChance = iBuildUnitProb + 10;

			iTrainInvaderChance += (bAggressiveAI ? 15 : 0);
			iTrainInvaderChance /= (bAssaultAssist ? 2 : 1);
			iTrainInvaderChance /= (bImportantCity ? 2 : 1);
			iTrainInvaderChance /= (bGetBetterUnits ? 2 : 1);

			iUnitsToTransport *= 9;
			iUnitsToTransport /= 10;

			if( (iUnitsToTransport > iTransportCapacity) && (iUnitsToTransport > (bAssaultAssist ? 2 : 4)*iBestSeaAssaultCapacity) )
			{
				// Already have enough
				iTrainInvaderChance /= 2;
			}
			else if( iUnitsToTransport < (iLocalTransports*iBestSeaAssaultCapacity) )
			{
				iTrainInvaderChance += 15;
			}

			if( getPopulation() < 4 )
			{
				// Let small cities build themselves up first
				iTrainInvaderChance /= (5 - getPopulation());
			}

			UnitTypeWeightArray invaderTypes;
			invaderTypes.push_back(std::make_pair(UNITAI_ATTACK_CITY, 100));
			invaderTypes.push_back(std::make_pair(UNITAI_COUNTER, 50));
			invaderTypes.push_back(std::make_pair(UNITAI_ATTACK, 40));
			if( kPlayer.AI_isDoStrategy(AI_STRATEGY_AIR_BLITZ) )
			{
				invaderTypes.push_back(std::make_pair(UNITAI_PARADROP, 20));
			}

			if( !bImportantCity && (iUnitsToTransport >= (iLocalTransports*iBestSeaAssaultCapacity)) )
			{
				// Have time to build barracks first
				if (AI_chooseBuilding(BUILDINGFOCUS_EXPERIENCE, 20))
				{
					return;
				}
			}

			if (AI_chooseLeastRepresentedUnit("invader units", invaderTypes, iTrainInvaderChance))
			{
				return;
			}

			if (iUnitCostPercentage < (iMaxUnitSpending))
			{
				int iMissileCarriers = kPlayer.AI_totalUnitAIs(UNITAI_MISSILE_CARRIER_SEA);
			
				if (!bFinancialTrouble && iMissileCarriers > 0 && !bImportantCity)
				{
					if( (iProductionRank <= ((kPlayer.getNumCities() / 2) + 1)) )
					{
						UnitTypes eBestMissileCarrierUnit = NO_UNIT;  
						kPlayer.AI_bestCityUnitAIValue(UNITAI_MISSILE_CARRIER_SEA, NULL, &eBestMissileCarrierUnit);
						if (eBestMissileCarrierUnit != NO_UNIT)
						{
							FAssert(GC.getUnitInfo(eBestMissileCarrierUnit).getDomainCargo() == DOMAIN_AIR);
							
							int iMissileCarrierAirNeeded = iMissileCarriers * GC.getUnitInfo(eBestMissileCarrierUnit).getCargoSpace();
							
							if ((kPlayer.AI_totalUnitAIs(UNITAI_MISSILE_AIR) < iMissileCarrierAirNeeded) || 
								(bPrimaryArea && (kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_MISSILE_CARRIER_SEA) * GC.getUnitInfo(eBestMissileCarrierUnit).getCargoSpace() < kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_MISSILE_AIR))))
							{
								// Don't always build missiles, more likely if really low
								if (AI_chooseUnit("need missiles", UNITAI_MISSILE_AIR, (kPlayer.AI_totalUnitAIs(UNITAI_MISSILE_AIR) < iMissileCarrierAirNeeded/2) ? 50 : 20))
								{
									return;
								}
							}
						}
					}
				}
			}
		}
	}
	
	m_iTempBuildPriority--;

	// Check for whether to produce planes to fill carriers
	if ( !bInhibitUnits && (bLandWar || bAssault) && iUnitCostPercentage < (iMaxUnitSpending))
	{			
		if (iCarriers > 0 && !bImportantCity)
		{
			UnitTypes eBestCarrierUnit = NO_UNIT;  
			kPlayer.AI_bestCityUnitAIValue(UNITAI_CARRIER_SEA, NULL, &eBestCarrierUnit);
			if (eBestCarrierUnit != NO_UNIT)
			{
				FAssert(GC.getUnitInfo(eBestCarrierUnit).getDomainCargo() == DOMAIN_AIR);
				
				int iCarrierAirNeeded = iCarriers * GC.getUnitInfo(eBestCarrierUnit).getCargoSpace();

				// Reduce chances if city gives no air experience
				if (kPlayer.AI_totalUnitAIs(UNITAI_CARRIER_AIR) < iCarrierAirNeeded)
				{
					if (AI_chooseUnit("need planes for carriers", UNITAI_CARRIER_AIR, (iFreeAirExperience > 0) ? -1 : 35))
					{
						return;
					}
				}
			}
		}
	}
	
	m_iTempBuildPriority--;

	//Afforess reduced 12 -> 6, since AI rarely reaches this logic, Added exemption for MAD players
	int chance = !GC.getGameINLINE().isOption(GAMEOPTION_RUTHLESS_AI) ? 6 : 3;
	if (!bInhibitUnits && !bAlwaysPeace && (kPlayer.AI_isDoStrategy(AI_STRATEGY_OWABWNW) || kPlayer.isEnabledMAD() || (getCitySorenRandNum(chance, "AI consider Nuke") == 0)))
	{
		if( !bFinancialTrouble )
		{
			int iTotalNukes = kPlayer.AI_totalUnitAIs(UNITAI_ICBM);
			int iNukesWanted = 1 + 2 * std::min(kPlayer.getNumCities(), GC.getGame().getNumCities() - kPlayer.getNumCities());
			//Afforess rolling randoms twice makes getting nukes much harder
			if ((iTotalNukes < iNukesWanted)/* && (getCitySorenRandNum(100, "AI train nuke MWAHAHAH") < (90 - (80 * iTotalNukes) / iNukesWanted))*/)
			{
				//Reordered, because nukes are more valuable than carriers
				if (AI_chooseUnit("ICBM (2)", UNITAI_ICBM))
				{
					return;
				}

				if ((pWaterArea != NULL))
				{
					if (AI_chooseUnit("need missile carrier", UNITAI_MISSILE_CARRIER_SEA, 50))
					{
						return;	
					}
				}
			}
		}
	}   

	m_iTempBuildPriority--;

	// Assault case now completely handled above
	if (/*!bUnitExempt && */!bInhibitUnits && !bAssault && (!bImportantCity || bDefenseWar) && (iUnitCostPercentage < iMaxUnitSpending))
    {
        if (!bFinancialTrouble && (bLandWar || (kPlayer.AI_isDoStrategy(AI_STRATEGY_DAGGER) && !bGetBetterUnits)))
        {
        	int iTrainInvaderChance = iBuildUnitProb + 10;

        	if (bAggressiveAI)
        	{
        		iTrainInvaderChance += 15;
        	}

			if( bGetBetterUnits )
			{
				iTrainInvaderChance /= 2;
			}
        	else if ((pArea->getAreaAIType(getTeam()) == AREAAI_MASSING) || (pArea->getAreaAIType(getTeam()) == AREAAI_ASSAULT_MASSING))
        	{
        		iTrainInvaderChance = (100 - ((100 - iTrainInvaderChance) / (bCrushStrategy ? 6 : 3)));
        	}        	

			if (AI_chooseBuilding(BUILDINGFOCUS_EXPERIENCE, 20, 0, bDefenseWar ? 10 : 30))
			{
				return;
			}

			UnitTypeWeightArray invaderTypes;
			invaderTypes.push_back(std::make_pair(UNITAI_ATTACK_CITY, 100));
			invaderTypes.push_back(std::make_pair(UNITAI_COUNTER, 50));
			invaderTypes.push_back(std::make_pair(UNITAI_ATTACK, 40));
			invaderTypes.push_back(std::make_pair(UNITAI_PARADROP, (kPlayer.AI_isDoStrategy(AI_STRATEGY_AIR_BLITZ) ? 30 : 20) / (bAssault ? 2 : 1)));
			if (!bAssault)
			{
				if (kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_PILLAGE) <= ((iNumCitiesInArea + 1) / 2))
				{
					invaderTypes.push_back(std::make_pair(UNITAI_PILLAGE, 30));
				}
			}

			if (AI_chooseLeastRepresentedUnit("invader units (2)", invaderTypes, iTrainInvaderChance))
			{
				return;
			}
        }
	}

	m_iTempBuildPriority--;

	if (!bInhibitUnits && (pWaterArea != NULL) && !bDefenseWar && !bAssault)
	{
		if( !bFinancialTrouble )
		{
			// Force civs with foreign colonies to build a few assault transports to defend the colonies
			if( kPlayer.AI_totalUnitAIs(UNITAI_ASSAULT_SEA) < (kPlayer.getNumCities() - iNumCapitalAreaCities)/3 )
			{
				if (AI_chooseUnit("colony defense assault ships", UNITAI_ASSAULT_SEA))
				{
					return;
				}
			}

			if (kPlayer.AI_calculateUnitAIViability(UNITAI_SETTLER_SEA, DOMAIN_SEA) < 61)
			{
				// Force civs to build escorts for settler_sea units
				if( kPlayer.AI_totalUnitAIs(UNITAI_SETTLER_SEA) > kPlayer.AI_getNumAIUnits(UNITAI_RESERVE_SEA) )
				{
					if (AI_chooseUnit("sea settler escorts", UNITAI_RESERVE_SEA))
					{
						return;
					}
				}
			}
		}
	}
	
	m_iTempBuildPriority--;

	//Arr.  Don't build pirates in financial trouble, as they'll be disbanded with high probability
	if (!bInhibitUnits && (pWaterArea != NULL) && !bLandWar && !bAssault && !bFinancialTrouble/* && !bUnitExempt*/) //k-mod
	{
		int iPirateCount = kPlayer.AI_totalWaterAreaUnitAIs(pWaterArea, UNITAI_PIRATE_SEA);
		int iNeededPirates = (1 + (pWaterArea->getNumTiles() / std::max(1, 200 - iBuildUnitProb)));
		iNeededPirates *= (20 + iWaterPercent);
		iNeededPirates /= 100;
		
		if (kPlayer.isNoForeignTrade())
		{
			iNeededPirates *= 3;
			iNeededPirates /= 2;
		}
		if (kPlayer.AI_totalWaterAreaUnitAIs(pWaterArea, UNITAI_PIRATE_SEA) < iNeededPirates)
		{
			if (kPlayer.AI_calculateUnitAIViability(UNITAI_PIRATE_SEA, DOMAIN_SEA) > 49)
			{
				if (AI_chooseUnit("pirates", UNITAI_PIRATE_SEA, iWaterPercent / (1 + iPirateCount)))
				{
					return;
				}
			}
		}
	}
	
	m_iTempBuildPriority--;

	if (!bInhibitUnits && !bLandWar && !bFinancialTrouble)
	{
		if ((pWaterArea != NULL) && (iWaterPercent > 40))
		{
			if (kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_SPY) > 0)
			{
				if (kPlayer.AI_totalWaterAreaUnitAIs(pWaterArea, UNITAI_SPY_SEA) == 0)
				{
					if (AI_chooseUnit("sea spy", UNITAI_SPY_SEA))
					{
						return;
					}
				}
			}
		}
	}
	
	m_iTempBuildPriority--;

	if (!bInhibitUnits && iBestSpreadUnitValue > ((iSpreadUnitThreshold * 40) / 100))
	{
		if (AI_chooseUnit(eBestSpreadUnit, UNITAI_MISSIONARY))
		{
			return;
		}
	}
		
	m_iTempBuildPriority--;

	if (!bInhibitUnits && (iTotalFloatingDefenders < iNeededFloatingDefenders && (!bFinancialTrouble || bLandWar)))
	{
		if (AI_chooseLeastRepresentedUnit("floating defenders", floatingDefenderTypes, 50))
		{
			return;
		}
	}
	
	m_iTempBuildPriority--;

	//	Koshling - protect against broken AI counts, which is known to happen occasionally
	int iNumSpies = std::max(0,kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_SPY));
	int iNeededSpies = iNumCitiesInArea / 3;
	iNeededSpies += isCapital() ? 1 : 0;
	// K-Mod
	if (kPlayer.AI_isDoStrategy(AI_STRATEGY_BIG_ESPIONAGE))
	{
		iNeededSpies *= 2;
	}

	if (!bInhibitUnits && iNumSpies < iNeededSpies)
	{
		//if (AI_chooseUnit("spy", UNITAI_SPY, 5 + 50 / (1 + iNumSpies)))
		if (AI_chooseUnit("spy", UNITAI_SPY, 30 * iNeededSpies / (3 * iNumSpies + iNeededSpies)))
		{
			return;
		}
	}
	
	if (!bInhibitUnits && bLandWar && !bDanger)
	{
		if (iNumSettlers < iMaxSettlers)
		{
			if (!bFinancialTrouble)
			{
				if (iAreaBestFoundValue > iMinFoundValue)
				{
					if (AI_chooseUnit("optional settlers", UNITAI_SETTLE))
					{
						return;
					}
				}
			}
		}
	}
	
	m_iTempBuildPriority--;

	if (!isHuman() &&
		(iProductionRank <= ((kPlayer.getNumCities() > 8) ? 3 : 2))
		&& (getPopulation() > 3))
	{
/************************************************************************************************/
/* Afforess	                  Start		 06/30/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/*
		int iWonderRand = 8 + getCitySorenRandNum(GC.getLeaderHeadInfo(getPersonalityType()).getWonderConstructRand(), "Wonder Construction Rand");
*/
		int iWonderRand = 8 + getCitySorenRandNum(GET_PLAYER(getOwnerINLINE()).getWonderConstructRand(), "Wonder Construction Rand");
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		
		// increase chance of going for an early wonder
		if (GC.getGameINLINE().getElapsedGameTurns() < (100 * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getConstructPercent() / 100) && iNumCitiesInArea > 1)
		{
			iWonderRand *= 35;
			iWonderRand /= 100;
		}
		else if (iNumCitiesInArea >= 3)
		{
			iWonderRand *= 30;
			iWonderRand /= 100;
		}
		else
		{
			iWonderRand *= 25;
			iWonderRand /= 100;
		}
		
		if (bAggressiveAI)
		{
			iWonderRand *= 2;
			iWonderRand /= 3;
		}
		
		int iWonderRoll = getCitySorenRandNum(100, "Wonder Build Rand");
		
		if (iProductionRank == 1)
		{
			iWonderRoll /= 2;
		}
		
		if (iWonderRoll < iWonderRand)
		{
			int iWonderMaxTurns = 20 + ((iWonderRand - iWonderRoll) * 2);
			if (bLandWar)
			{
				iWonderMaxTurns /= 2;
			}
			
			if (AI_chooseBuilding(BUILDINGFOCUS_WORLDWONDER, iWonderMaxTurns))
			{
				if( gCityLogLevel >= 2 ) logBBAI("      City %S uses oppurtunistic wonder build 3", getName().GetCString());
				return;
			}
		}
	}
	
	m_iTempBuildPriority--;

	if (!bInhibitUnits && iUnitCostPercentage < iMaxUnitSpending + 4 && !bFinancialTrouble)
	{
		if ((iAircraftHave * 2 >= iAircraftNeed) && (iAircraftHave < iAircraftNeed))
		{
			int iOdds = 33;

			if( iFreeAirExperience > 0 || (iProductionRank <= (1 + kPlayer.getNumCities()/2)) )
			{
				iOdds = -1;
			}

			if (AI_chooseLeastRepresentedUnit("air units", airUnitTypes, iOdds))
			{
				return;
			}
		}
	}

	m_iTempBuildPriority--;

	if (!bLandWar)
	{		
		if ((iCulturePressure > 90) || kPlayer.AI_isDoVictoryStrategy(AI_VICTORY_CULTURE2))
		{
			if (!isHuman() || AI_isEmphasizeCommerce(COMMERCE_CULTURE))
			{
				if (AI_chooseBuilding(BUILDINGFOCUS_CULTURE, 20))
				{
					if( gCityLogLevel >= 2 ) logBBAI("      City %S uses cultural pressure/cultural victory 3", getName().GetCString());
					return;
				}
			}
		}

		if (!bInhibitUnits && pWaterArea != NULL && bFinancialTrouble)
		{
			if (kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_MISSIONARY) > 0)
			{
				if (kPlayer.AI_totalWaterAreaUnitAIs(pWaterArea, UNITAI_MISSIONARY_SEA) == 0)
				{
					if (AI_chooseUnit("sea missionary", UNITAI_MISSIONARY_SEA))
					{
						return;
					}
				}
			}
		}
	}

	m_iTempBuildPriority--;

	if (!isHuman() || AI_isEmphasizeCommerce(COMMERCE_CULTURE))
	{
		if (getCommerceRateTimes100(COMMERCE_CULTURE) == 0)
		{
			if (AI_chooseBuilding(BUILDINGFOCUS_CULTURE, 30))
			{
				return;
			}
		}
	}

//TB Build Mod (Move up in priority so this takes place before building for invasions)
#ifndef C2C_BUILD
	if (!bAlwaysPeace )
	{
	    if (!bDanger)
	    {
			if (AI_chooseBuilding(BUILDINGFOCUS_EXPERIENCE, 20, 0, 3*getPopulation()))
            {
                return;
            }
	    }

		if (AI_chooseBuilding(BUILDINGFOCUS_DEFENSE, 20, 0, bDanger ? -1 : 3*getPopulation()))
		{
			return;
		}
		
		if (bDanger)
	    {
            if (AI_chooseBuilding(BUILDINGFOCUS_EXPERIENCE, 20, 0, 2*getPopulation()))
            {
                return;
            }
	    }
	}

//TB Build Mod (Remove unnecessary elements)
	if (AI_chooseBuilding(BUILDINGFOCUS_PRODUCTION, 20, 4))
	{
		if( gCityLogLevel >= 2 ) logBBAI("      City %S uses choose BUILDINGFOCUS_PRODUCTION 2", getName().GetCString());
		return;
	}
#endif
	
	m_iTempBuildPriority--;

	//20 means 5g or ~2 happiness...
	if (AI_chooseBuilding(iEconomyFlags, 15, (20*iEcononmyFlagsThreasholdWeighting)/100))
	{
		if( gCityLogLevel >= 2 ) logBBAI("      City %S uses choose iEconomyFlags 2", getName().GetCString());
		return;
	}

	m_iTempBuildPriority--;

	if (!bLandWar)
	{
		if (AI_chooseBuilding(iEconomyFlags, 40, (8*iEcononmyFlagsThreasholdWeighting)/100))
		{
			if( gCityLogLevel >= 2 ) logBBAI("      City %S uses choose iEconomyFlags 3", getName().GetCString());
			return;
		}

		if (!isHuman() || AI_isEmphasizeCommerce(COMMERCE_CULTURE))
		{
			if (iCulturePressure > 50)
			{
				if (AI_chooseBuilding(BUILDINGFOCUS_CULTURE, 60))
				{
					if( gCityLogLevel >= 2 ) logBBAI("      City %S uses choose cultural pressure 2", getName().GetCString());
					return;
				}
			}
		}

		if (!bInhibitUnits && pWaterArea != NULL)
		{
			if (bPrimaryArea)
			{
				if (kPlayer.AI_totalWaterAreaUnitAIs(pWaterArea, UNITAI_EXPLORE_SEA) < std::min(1, kPlayer.AI_neededExplorers(pWaterArea)))
				{
					if (AI_chooseUnit("explore sea", UNITAI_EXPLORE_SEA))
					{
						return;
					}
				}
			}
		}

		if (!isHuman() || AI_isEmphasizeYield(YIELD_PRODUCTION))
		{
			if (getBaseYieldRate(YIELD_PRODUCTION) >= 8)
			{
				if (AI_chooseBuilding(BUILDINGFOCUS_PRODUCTION, 80))
				{
					if( gCityLogLevel >= 2 ) logBBAI("      City %S uses choose BUILDINGFOCUS_PRODUCTION 3", getName().GetCString());
					return;
				}
			}
		}
	}

	m_iTempBuildPriority--;

	//	If there are no city counter units in the vicinity best create 1
	if (!bInhibitUnits && plot()->plotCount(PUF_isUnitAIType, UNITAI_CITY_COUNTER, -1, NULL, getOwnerINLINE(), NO_TEAM, NULL, -1, -1, 2) == 0)
	{
		if (AI_chooseUnit("city counter units needed locally", UNITAI_CITY_COUNTER))
		{
			return;
		}
	}

	m_iTempBuildPriority--;

	//	If there are no pillage counter units in the vicinity best create 1
	if (!bInhibitUnits && plot()->plotCount(PUF_isUnitAIType, UNITAI_PILLAGE_COUNTER, -1, NULL, getOwnerINLINE(), NO_TEAM, NULL, -1, -1, 2) == 0)
	{
		if (AI_chooseUnit("pillage counter units needed locally", UNITAI_PILLAGE_COUNTER))
		{
			return;
		}
	}

	m_iTempBuildPriority--;

	// we do a similar check lower, in the landwar case
	if (!bLandWar && bFinancialTrouble)
	{
		if (!isHuman() || AI_isEmphasizeCommerce(COMMERCE_GOLD))
		{
			if (AI_chooseBuilding(BUILDINGFOCUS_GOLD))
			{
				if( gCityLogLevel >= 2 ) logBBAI("      City %S uses choose financial trouble gold", getName().GetCString());
				return;
			}
		}
	}

	m_iTempBuildPriority--;

	//	low priority property control (bad property > 5% through op range - choose unit to deal if possible)
	if ( AI_choosePropertyControlUnit( 5 ) )
	{
		return;
	}
	
	m_iTempBuildPriority--;

	if ( AI_chooseHealerUnit() )
	{
		return;
	}
    
	m_iTempBuildPriority--;

	bChooseUnit = false;
	if (!bInhibitUnits && iUnitCostPercentage < iMaxUnitSpending + 5)
	{
		if ((bLandWar) ||
			  ((kPlayer.getNumCities() <= 3) && (GC.getGameINLINE().getElapsedGameTurns() < 60)) ||
			  (getCitySorenRandNum(100, "AI Build Unit Production") < AI_buildUnitProb()) ||
				(isHuman() && (getGameTurnFounded() == GC.getGameINLINE().getGameTurn())))
		{
			if (AI_chooseUnit("optional units"))
			{
				return;
			}

			bChooseUnit = true;
		}
	}

	m_iTempBuildPriority--;

	// BBAI TODO: Temporary for testing
	//if( getOwnerINLINE()%2 == 1 )
	//{
		// Only cities with reasonable production
		if (!isHuman() && (iProductionRank <= ((kPlayer.getNumCities() > 8) ? 3 : 2))
		&& (getPopulation() > 3))
		{
			if (AI_chooseProject())
			{
				if( gCityLogLevel >= 2 ) logBBAI("      City %S uses choose project 2", getName().GetCString());
				return;
			}
		}
	//}
 
Part V
Spoiler :
Code:
	m_iTempBuildPriority--;

	if (AI_chooseBuilding())
	{
		if( gCityLogLevel >= 2 ) logBBAI("      City %S uses choose building by probability", getName().GetCString());
		return;
	}
	
	m_iTempBuildPriority--;

	if (!bChooseUnit && !bFinancialTrouble && kPlayer.AI_isDoStrategy(AI_STRATEGY_FINAL_WAR))
	{
		if (AI_chooseUnit("final war units"))
		{
			return;
		}
	}

	m_iTempBuildPriority--;

	//	Koshling.  AI shouldn't choose gold as often as it does.  If we have plenty of
	//	gold prefer research most of the time

	//	Set up weights 0-100 for each commerce type to weight the choice (gold weigth can actuially go higher than
	//	100, but only if we already have less gold than our target in which case we should already have unconditonally
	//	gone for gold earlier in this choice)
	int commerceWeights[NUM_COMMERCE_TYPES];

	commerceWeights[COMMERCE_GOLD] = std::max(0,100-(GET_PLAYER(getOwnerINLINE()).getGold() - GET_PLAYER(getOwnerINLINE()).AI_goldTarget())*100/std::max(1,GET_PLAYER(getOwnerINLINE()).AI_goldTarget()));
	if (isHuman() && !AI_isEmphasizeCommerce(COMMERCE_GOLD))
	{
		commerceWeights[COMMERCE_GOLD] = 0;
	}

	commerceWeights[COMMERCE_RESEARCH] = 50;	//	Can't think of a good measure for research pressure so just set to a middling value
	if (isHuman() && !AI_isEmphasizeCommerce(COMMERCE_RESEARCH))
	{
		commerceWeights[COMMERCE_RESEARCH] = 0;
	}
	commerceWeights[COMMERCE_CULTURE] = iCulturePressure;
	if (isHuman() && !AI_isEmphasizeCommerce(COMMERCE_CULTURE))
	{
		commerceWeights[COMMERCE_CULTURE] = 0;
	}
	commerceWeights[COMMERCE_ESPIONAGE] = 10;	//	Is this ever really worthwhile?

	if (!AI_chooseProcess(NO_COMMERCE, commerceWeights))
	{
		if (!AI_finalProcessSelection())
		{
			FAssert(false);
		}
	}
}
This last portion is the 'mousetrap' that should never allow the city to go without a selection unless there's another issue somewhere where it isn't looking for a selection when it should, or if the city doesn't have any process (build gold/research etc...) it can select for some reason.
 
I got v11, 16, 19, 21, 22 of C2C. The rest can be found on the SVN iirc. I know v27 thru v36 can be. I had more but lost v1 thru 10 to a HD crash couple of years ago.

Plus Rise of Mankind v1.03 , 2.5, 2.71, 2.81, and 2.92.

I may have some early AND on my older Comp too.

JosEPh

If you've got a v11 CvUnit from the sources file, let's see it. That should be before any combat mod stuff ever went in.
 
If you've got a v11 CvUnit from the sources file, let's see it. That should be before any combat mod stuff ever went in.

Which one is need?? I have one from R2R from the last update they did.
 
Thanks SO! I've been asking for a few weeks here. Glad someone finally noticed that could provide it. Hopefully this will give me the coding I need. Thankfully I now possess a much better understanding of the elements in the function I need to restore then re-edit to update it to the current C2C combat features properly.

I'll work on this tomorrow I think.

I just committed a fix to the city process issue Pit was having. It actually was a fairly severe impediment to the AI as he noted.
 
8953 Jade Death Mask building is a normal building, but has the star like a National or World building.
 
Also a long standing bug I can't really pin down: there is a period in the early game I can't place wine imprpovement, between plant picking and a true winery. Same for chopping jungles, at the start chopping works, then it doesn't, and after iron working it works again.
 
It's because Fruit picker becomes obsolete with Orchards but Winery requires Fermentation.
 
Ok, I THINK I've made some headway here. Apparently it's somehow possible for cities to evaluate all the way through all possibilities and come up with no answer for what to set to build so I've built a failsafe mousetrap at the end to make sure that it at least picks a valuable process.

I'm sure there are plenty of places this selection routine could be improved but if you'd like to go through it line by line, be my guest.:
Part I
Spoiler :
Code:
void CvCityAI::AI_chooseProduction()
{
	PROFILE_FUNC();

	CvArea* pWaterArea;
	bool bWasFoodProduction;
	bool bLandWar;
	bool bAssault;
	bool bDefenseWar;
	bool bPrimaryArea;
	bool bFinancialTrouble;
	bool bDanger;
	bool bChooseUnit;
	bool bInhibitUnits = false;
	int iProductionRank;
	int iCulturePressure;
	m_bRequestedBuilding = false;	
	m_bRequestedUnit = false;	

	CvPlayerAI& kPlayer = GET_PLAYER(getOwnerINLINE());

	if (kPlayer.isAnarchy())
	{
		return;
	}

	bDanger = AI_isDanger();
	
	m_iBuildPriority = CITY_BUILD_PRIORITY_CEILING;
	m_iTempBuildPriority = CITY_BUILD_PRIORITY_CEILING;

	// only clear the dirty bit if we actually do a check, multiple items might be queued
	AI_setChooseProductionDirty(false);
/************************************************************************************************/
/* Afforess	                  Start		 04/22/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if(GC.getUSE_AI_CHOOSE_PRODUCTION_CALLBACK())
	{
		PYTHON_ACCESS_LOCK_SCOPE

		// allow python to handle it
		CyCity* pyCity = new CyCity(this);
		CyArgsList argsList;
		argsList.add(gDLL->getPythonIFace()->makePythonObject(pyCity));	// pass in city class
		long lResult=0;
		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "AI_chooseProduction", argsList.makeFunctionArgs(), &lResult);
		delete pyCity;	// python fxn must not hold on to this pointer
		if (lResult == 1)
		{
			return;
		}
	}

	if (isHuman() && isProductionAutomated())
	{
		if (!GET_PLAYER(getOwnerINLINE()).isOption(PLAYEROPTION_MODDER_3))
		{
			AI_buildGovernorChooseProduction();
			return;
		}
		else
		{
			for (int iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
			{
				if (AI_isEmphasizeCommerce((CommerceTypes)iI))
				{
					bInhibitUnits = true;
				}
			}
			for (int iI = 0; iI < NUM_YIELD_TYPES; iI++)
			{
				if (AI_isEmphasizeYield((YieldTypes)iI))
				{
					bInhibitUnits = true;
				}
			}
		}
	}

/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	
	CvArea* pArea = area();
	pWaterArea = waterArea(true);
	bool bMaybeWaterArea = false;
	bool bWaterDanger = false;
    
	if (pWaterArea != NULL)
	{
		bMaybeWaterArea = true;
		if (!GET_TEAM(getTeam()).AI_isWaterAreaRelevant(pWaterArea))
		{
			pWaterArea = NULL;
		}

		bWaterDanger = kPlayer.AI_getWaterDanger(plot(), 4) > 0;
	}

	bWasFoodProduction = isFoodProduction();
	//AIAndy: Not used here at the moment
	//bool bHasMetHuman = GET_TEAM(getTeam()).hasMetHuman();
	bool bMassing = (pArea->getAreaAIType(getTeam()) == AREAAI_ASSAULT_MASSING);
	bLandWar = ((pArea->getAreaAIType(getTeam()) == AREAAI_OFFENSIVE) || (pArea->getAreaAIType(getTeam()) == AREAAI_DEFENSIVE) || bMassing);
	bDefenseWar = (pArea->getAreaAIType(getTeam()) == AREAAI_DEFENSIVE);
	bool bAssaultAssist = (pArea->getAreaAIType(getTeam()) == AREAAI_ASSAULT_ASSIST);
	bAssault = bAssaultAssist || (pArea->getAreaAIType(getTeam()) == AREAAI_ASSAULT) || bMassing;
	bPrimaryArea = kPlayer.AI_isPrimaryArea(pArea);
	bFinancialTrouble = kPlayer.AI_isFinancialTrouble();
	iCulturePressure = AI_calculateCulturePressure();
	int iNumCitiesInArea = pArea->getCitiesPerPlayer(getOwnerINLINE());
	bool bImportantCity = false; //be very careful about setting this.
	bool bBigCultureCity = false;
	int iCultureRateRank = findCommerceRateRank(COMMERCE_CULTURE);
    int iCulturalVictoryNumCultureCities = GC.getGameINLINE().culturalVictoryNumCultureCities();

	int iWarSuccessRatio = GET_TEAM(getTeam()).AI_getWarSuccessCapitulationRatio();
	int iEnemyPowerPerc = GET_TEAM(getTeam()).AI_getEnemyPowerPercent(true);
	int iWarTroubleThreshold = 0;

	//	Are our best worker units one-shot usage (mostly)?
	bool bBestWorkerIsOneShot = false;
	//TB OOS Debug: Undefined variable causing an OOS
	int iUnitValue = 0;
	UnitTypes eBestWorker = AI_bestUnitAI(UNITAI_WORKER, iUnitValue, false, true);
	if ( eBestWorker != NO_UNIT )
	{
		int	iNoKillBuildsCount = 0;
		int	iKillBuildsCount = 0;

		for (int iI = 0; iI < GC.getNumBuildInfos(); ++iI)
		{
			if (GC.getUnitInfo(eBestWorker).getBuilds(iI))
			{
				if ( GC.getBuildInfo((BuildTypes)iI).isKill() )
				{
					iKillBuildsCount++;
				}
				else
				{
					iNoKillBuildsCount++;
				}
			}
		}

		//	Empirical ratio needed to distinguish C2C gatherer, but should hopefully
		//	be a reasonable heuristic should any similar units be added in future
		bBestWorkerIsOneShot = (3*iKillBuildsCount >= iNoKillBuildsCount);
	}

	if( bLandWar && iWarSuccessRatio < 30 )
	{
		iWarTroubleThreshold = std::max(3,(-iWarSuccessRatio/8));
	}

	if( !bLandWar && !bAssault && GET_TEAM(getTeam()).isAVassal() )
	{
		bLandWar = GET_TEAM(getTeam()).isMasterPlanningLandWar(area());

		if( !bLandWar )
		{
			bAssault = GET_TEAM(getTeam()).isMasterPlanningSeaWar(area());
		}
	}

    bool bGetBetterUnits = kPlayer.AI_isDoStrategy(AI_STRATEGY_GET_BETTER_UNITS);
    bool bAggressiveAI = GC.getGameINLINE().isOption(GAMEOPTION_AGGRESSIVE_AI);
    bool bAlwaysPeace = GC.getGameINLINE().isOption(GAMEOPTION_ALWAYS_PEACE);

	int iUnitCostPercentage = (kPlayer.calculateUnitCost() * 100) / std::max(1, kPlayer.calculatePreInflatedCosts());
	int iWaterPercent = AI_calculateWaterWorldPercent();
	
	int iBuildUnitProb = AI_buildUnitProb();
    
    int iExistingWorkers = kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_WORKER);
    int iNeededWorkers = kPlayer.AI_neededWorkers(pArea);
	// Sea worker need independent of whether water area is militarily relevant
	int iNeededSeaWorkers = (bMaybeWaterArea) ? AI_neededSeaWorkers() : 0;
	int iExistingSeaWorkers = (waterArea(true) != NULL) ? kPlayer.AI_totalWaterAreaUnitAIs(waterArea(true), UNITAI_WORKER_SEA) : 0;

    int iTargetCulturePerTurn = AI_calculateTargetCulturePerTurn();
    
    int iAreaBestFoundValue;
    int iNumAreaCitySites = kPlayer.AI_getNumAreaCitySites(getArea(), iAreaBestFoundValue);
    
    int iWaterAreaBestFoundValue = 0;
	CvArea* pWaterSettlerArea = pWaterArea;
	if( pWaterSettlerArea == NULL )
	{
		pWaterSettlerArea = GC.getMap().findBiggestArea(true);

		if( GET_PLAYER(getOwnerINLINE()).AI_totalWaterAreaUnitAIs(pWaterSettlerArea, UNITAI_SETTLER_SEA) == 0 )
		{
			pWaterSettlerArea = NULL;
		}
	}
    int iNumWaterAreaCitySites = (pWaterSettlerArea == NULL) ? 0 : kPlayer.AI_getNumAdjacentAreaCitySites(pWaterSettlerArea->getID(), getArea(), iWaterAreaBestFoundValue);
    int iNumSettlers = kPlayer.AI_totalUnitAIs(UNITAI_SETTLE) + GET_PLAYER(getOwnerINLINE()).getContractBroker().numRequestsOutstanding(UNITAI_SETTLE);
    
    bool bIsCapitalArea = false;
	int iNumCapitalAreaCities = 0;
    if (kPlayer.getCapitalCity() != NULL)
    {
		iNumCapitalAreaCities = kPlayer.getCapitalCity()->area()->getCitiesPerPlayer(getOwnerINLINE());
    	if (getArea() == kPlayer.getCapitalCity()->getArea())
    	{
    		bIsCapitalArea = true;
    	}
    }
        
    int iMaxSettlers = 0;
    if (!bFinancialTrouble && GET_PLAYER(getOwnerINLINE()).bestBuildableUnitForAIType(NO_DOMAIN, UNITAI_SETTLE) != NO_UNIT)
    {
     	iMaxSettlers= std::min((kPlayer.getNumCities() + 1) / 2, iNumAreaCitySites + iNumWaterAreaCitySites);
     	if (bLandWar || bAssault)
     	{
     		iMaxSettlers = (iMaxSettlers + 2) / 3;
     	}

		if (kPlayer.getCityLimit() > 0)
		{
			if ( kPlayer.getCityOverLimitUnhappy() > 0 )
			{
				//	Soft limit.  If we already have unhappy cities don't create
				//	settlers that will increase overall unhappiness as they found
				//	new cities
				if ( kPlayer.AI_getOverallHappyness() < 0 )
				{
					iMaxSettlers = std::min(iMaxSettlers, std::max(0,kPlayer.getCityLimit() - kPlayer.getNumCities()));
				}
			}
			else
			{
				//	Hard limit - don't stockpile more than 2 settlers
				iMaxSettlers = std::min(iMaxSettlers,kPlayer.getCityLimit() - kPlayer.getNumCities() + 2);
			}
		}
    }
/************************************************************************************************/
/* Afforess	                  Start		 06/29/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/	
	// AIAndy: Not used here at the moment
	//bool bDevelopingCity = isDevelopingCity();
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

    
    bool bChooseWorker = false;
    
	int iEconomyFlags = 0;
	int iEconomyFlagBits = 0;


	if ( !isHuman() || AI_isEmphasizeYield(YIELD_PRODUCTION) )
	{
		iEconomyFlags |= BUILDINGFOCUS_PRODUCTION;
		iEconomyFlagBits++;
	}
	if ( !isHuman() || AI_isEmphasizeYield(YIELD_COMMERCE) )
	{
		iEconomyFlags |= BUILDINGFOCUS_GOLD;
		iEconomyFlagBits++;
	}
	if ( !isHuman() || AI_isEmphasizeCommerce(COMMERCE_RESEARCH) )
	{
		iEconomyFlags |= BUILDINGFOCUS_RESEARCH;
		iEconomyFlagBits++;
	}
	if ( !bInhibitUnits )	//	This is actually a proxy for the human owner having set no explicit preferences
	{
		iEconomyFlags |= BUILDINGFOCUS_MAINTENANCE;
		iEconomyFlags |= BUILDINGFOCUS_HAPPY;
		iEconomyFlags |= BUILDINGFOCUS_HEALTHY;

		iEconomyFlagBits += 3;
	}
	if (AI_isEmphasizeGreatPeople())
	{
		iEconomyFlags |= BUILDINGFOCUS_SPECIALIST;
		iEconomyFlagBits++;
	}
	if (!GC.getGameINLINE().isOption(GAMEOPTION_NO_ESPIONAGE))
	{
		iEconomyFlags |= BUILDINGFOCUS_ESPIONAGE;
		iEconomyFlagBits++;
	}

	//	Normalize threholds using this against the number of bits we are including
	int iEcononmyFlagsThreasholdWeighting = (100*iEconomyFlagBits)/8;

	if (iNumCitiesInArea > 2)
	{
		if (kPlayer.AI_isDoVictoryStrategy(AI_VICTORY_CULTURE2))
		{
			if (iCultureRateRank <= iCulturalVictoryNumCultureCities + 1)
			{
				bBigCultureCity = true;

				// if we do not have enough cities, then the highest culture city will not get special attention
				if (iCultureRateRank > 1 || (kPlayer.getNumCities() > (iCulturalVictoryNumCultureCities + 1)))
				{
					if ((((iNumAreaCitySites + iNumWaterAreaCitySites) > 0) && (kPlayer.getNumCities() < 6)) && (getCitySorenRandNum(2, "AI Less Culture More Expand") == 0))
					{
						bImportantCity = false;
					}
					else
					{
						bImportantCity = true;
					}
				}
            }
        }
	}

	// Free experience for various unit domains
	int iFreeLandExperience = getSpecialistFreeExperience() + getDomainFreeExperience(DOMAIN_LAND);
	// AIAndy: Not used here at the moment
	//int iFreeSeaExperience = getSpecialistFreeExperience() + getDomainFreeExperience(DOMAIN_SEA);
	int iFreeAirExperience = getSpecialistFreeExperience() + getDomainFreeExperience(DOMAIN_AIR);

	clearOrderQueue();

	if (bWasFoodProduction)
	{
		AI_assignWorkingPlots();
	}

	iProductionRank = findYieldRateRank(YIELD_PRODUCTION);

	// K-Mod, military exemption for commerce cities and underdeveloped cities
	//bool bUnitExempt = false;
	//if (kPlayer.AI_isDoStrategy(AI_STRATEGY_ECONOMY_FOCUS))
	//{
	//	bUnitExempt = true;
	//}
	//else if (iProductionRank > kPlayer.getNumCities() / 2)
	//{
	//	bool bBelowMedian = true;
	//	for (int iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
	//	{
	//		// I'd use the total commerce rank, but there currently isn't a cached value of that.
	//		int iRank = findCommerceRateRank((CommerceTypes)iI);
	//		if (iRank < iProductionRank)
	//		{
	//			bUnitExempt = true;
	//			break;
	//		}
	//		if (iRank < kPlayer.getNumCities() / 2)
	//		{
	//			bBelowMedian = false;
	//		}
	//	}

	//	if (bBelowMedian)
	//	{
	//		bUnitExempt = true;
	//	}
	//}
	////Exemptions (Afforess)
	//if (isCapital() || kPlayer.getNumCities() < 3)
	//{
	//	bUnitExempt = false;
	//}
	// K-Mod end

	if( gCityLogLevel >= 3 ) logBBAI("      City %S pop %d considering new production: iProdRank %d, iBuildUnitProb %d", getName().GetCString(), getPopulation(), iProductionRank, iBuildUnitProb);

	// -------------------- BBAI Notes -------------------------
	// Start special circumstances

	// -------------------- BBAI Notes -------------------------
	// Barbarian city build priorities
	if (isBarbarian())
	{
		if( gCityLogLevel >= 3 )
		{
			logBBAI("      Barb city %S - area workers %d (needed %d), local %d (needed %d)", getName().GetCString(), iExistingWorkers, iNeededWorkers, AI_getWorkersHave(), AI_getWorkersNeeded());
		}
		if (!AI_isDefended(plot()->plotStrength(UNITVALUE_FLAGS_DEFENSIVE, PUF_isUnitAIType, UNITAI_ATTACK, -1, getOwnerINLINE()))) // XXX check for other team's units?
		{
			if (AI_chooseDefender("barbarian defenders"))
			{
				return;
			}

			if (AI_chooseUnit("barbarian lack of defense", UNITAI_ATTACK))
			{
				return;
			}
		}
		
		if (!bDanger && (2*iExistingWorkers < iNeededWorkers) && (AI_getWorkersNeeded() > 0) && (AI_getWorkersHave() == 0))
		{
			if( getPopulation() > 1 || (GC.getGameINLINE().getGameTurn() - getGameTurnAcquired() > (15 * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getTrainPercent())/100) )
			{
				if (AI_chooseUnit("barbarian worker for established city", UNITAI_WORKER))
				{
					return;
				}
			}			
		}

		if (!bDanger && !bWaterDanger && (iNeededSeaWorkers > 0))
		{
			if (AI_chooseUnit("barbarian navy", UNITAI_WORKER_SEA))
			{
				return;
			}
		}
		
		iBuildUnitProb += (3 * iFreeLandExperience);
		
		bool bRepelColonists = false;
		if( area()->getNumCities() > area()->getCitiesPerPlayer(BARBARIAN_PLAYER) + 2 )
		{
			if( area()->getCitiesPerPlayer(BARBARIAN_PLAYER) > area()->getNumCities()/3 )
			{
				// New world scenario with invading colonists ... fight back!
				bRepelColonists = true;
				iBuildUnitProb += 8*(area()->getNumCities() - area()->getCitiesPerPlayer(BARBARIAN_PLAYER));
			}
		}

		bChooseUnit = false;
		if (!bDanger && getCitySorenRandNum(100, "AI Build Unit Production") > iBuildUnitProb)
		{
			
			int iBarbarianFlags = 0;
			if( getPopulation() < 4 ) iBarbarianFlags |= BUILDINGFOCUS_FOOD;
			iBarbarianFlags |= BUILDINGFOCUS_PRODUCTION;
			iBarbarianFlags |= BUILDINGFOCUS_EXPERIENCE;
			if( getPopulation() > 3 ) iBarbarianFlags |= BUILDINGFOCUS_DEFENSE;
			
			if (AI_chooseBuilding(iBarbarianFlags, 15))
			{
				if( gCityLogLevel >= 2 ) logBBAI("      City %S uses barb AI_chooseBuilding with flags and iBuildUnitProb = %d", getName().GetCString(), iBuildUnitProb);
				return;
			}

			if( getCitySorenRandNum(100, "AI Build Unit Production") > iBuildUnitProb)
			{
				if (AI_chooseBuilding())
				{
					if( gCityLogLevel >= 2 ) logBBAI("      City %S uses barb AI_chooseBuilding without flags and iBuildUnitProb = %d", getName().GetCString(), iBuildUnitProb);
					return;
				}
			}
		}
		
		if (plot()->plotCount(PUF_isUnitAIType, UNITAI_ASSAULT_SEA, -1, NULL, getOwnerINLINE()) > 0)
		{
			if (AI_chooseUnit("barbarian choose attack city for transports", UNITAI_ATTACK_CITY))
			{
				return;
			}
		}
		
		if (!bDanger && (pWaterArea != NULL) && (iWaterPercent > 30))
		{
			if (getCitySorenRandNum(3, "AI Coast Raiders!") == 0)
			{
				if (kPlayer.AI_totalUnitAIs(UNITAI_ASSAULT_SEA) <= (1 + kPlayer.getNumCities() / 2))
				{
					if (AI_chooseUnit("barbarian transports", UNITAI_ASSAULT_SEA))
					{
						return;
					}
				}
			}
			if (getCitySorenRandNum(110, "AI arrrr!") < (iWaterPercent + 10))
			{
				if (kPlayer.AI_totalUnitAIs(UNITAI_PIRATE_SEA) <= kPlayer.getNumCities())
				{
					if (AI_chooseUnit("barbarian pirates", UNITAI_PIRATE_SEA))
					{
						return;
					}
				}
				
				if (kPlayer.AI_totalAreaUnitAIs(pWaterArea, UNITAI_ATTACK_SEA) < iNumCitiesInArea)
				{
					if (AI_chooseUnit("barbarian sea attack", UNITAI_ATTACK_SEA))
					{
						return;
					}
				}
			}
		}

		if (getCitySorenRandNum(2, "Barb worker") == 0)
		{
			if (!bDanger && (iExistingWorkers < iNeededWorkers) && (AI_getWorkersNeeded() > 0) && (AI_getWorkersHave() == 0))
			{
				if( getPopulation() > 1 )
				{
					if (AI_chooseUnit("barbarian worker", UNITAI_WORKER))
					{
						return;
					}
				}			
			}
		}

		UnitTypeWeightArray barbarianTypes;
		barbarianTypes.push_back(std::make_pair(UNITAI_ATTACK, 125));
		barbarianTypes.push_back(std::make_pair(UNITAI_ATTACK_CITY, (bRepelColonists ? 200 : 100)));
		barbarianTypes.push_back(std::make_pair(UNITAI_COUNTER, 100));
		barbarianTypes.push_back(std::make_pair(UNITAI_CITY_DEFENSE, 50));

		if (AI_chooseLeastRepresentedUnit("barbarian units", barbarianTypes))
		{
			return;
		}
		
		if (AI_chooseUnit("barbarian last resort"))
		{
			return;
		}
		
		return;
	}
	
//TB Build Mod (is considered a poor strategy now)	// if we need to pop borders, then do that immediately if we have drama and can do it
#ifndef C2C_BUILD
	// if we need to pop borders, then do that immediately if we have drama and can do it
	if ((iTargetCulturePerTurn > 0) && (getCultureLevel() <= (CultureLevelTypes) 1))
	{
        if (AI_chooseProcess(COMMERCE_CULTURE))
        {
            return;
        }
	}
#endif

/************************************************************************************************/
/* REVOLUTION_MOD                         06/11/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if( kPlayer.isRebel() )
	{		
		UnitTypeWeightArray rebelDefenseTypes;
		rebelDefenseTypes.push_back(std::make_pair(UNITAI_CITY_DEFENSE, 100));
		rebelDefenseTypes.push_back(std::make_pair(UNITAI_COUNTER, 100));
		rebelDefenseTypes.push_back(std::make_pair(UNITAI_COLLATERAL, 100));
		rebelDefenseTypes.push_back(std::make_pair(UNITAI_ATTACK, 100));

		UnitTypeWeightArray rebelOffenseTypes;
		rebelOffenseTypes.push_back(std::make_pair(UNITAI_ATTACK, 125));
		rebelOffenseTypes.push_back(std::make_pair(UNITAI_COUNTER, 100));
		rebelOffenseTypes.push_back(std::make_pair(UNITAI_ATTACK_CITY, 75));

		if( isOccupation() )
		{
			// Probably just captured ... may be getting defensive units, 
			// but need to build offense to keep rolling
			if( bLandWar || bDanger )
			{
				if (AI_chooseLeastRepresentedUnit("rebel offense", rebelOffenseTypes))
				{
					return;
				}
			}
		}
		else
		{
			// City Defense
			if (plot()->plotCount(PUF_isUnitAIType, UNITAI_CITY_DEFENSE, -1, NULL, getOwnerINLINE()) < (AI_minDefenders()))
			{
				if (AI_chooseUnit("rebel city defense", UNITAI_CITY_DEFENSE))
				{
					return;
				}

				if (AI_chooseDefender("rebel city defense (non-specific)"))
				{
					return;
				}
			}

			// Area defense
			int iNeededFloatingDefenders = kPlayer.AI_getTotalFloatingDefendersNeeded(pArea);
 			int iTotalFloatingDefenders = kPlayer.AI_getTotalFloatingDefenders(pArea);
			
			if (iTotalFloatingDefenders < ((iNeededFloatingDefenders + 1) / (2)))
			{
				if (AI_chooseLeastRepresentedUnit("rebel defense", rebelDefenseTypes))
				{
					return;
				}
			}

			// Offensive rebel units
			if( bDanger || (getCitySorenRandNum(100, "AI Build Unit Production") < AI_buildUnitProb()) )
			{
				if( (getYieldRate(YIELD_PRODUCTION) > 5) )
				{
					// Air units
					int iBestDefenseValue = kPlayer.AI_bestCityUnitAIValue(UNITAI_DEFENSE_AIR, this);

					if( iBestDefenseValue > 0 )
					{
						UnitTypes eBestAttackAircraft = NO_UNIT;
						int iBestAirValue = kPlayer.AI_bestCityUnitAIValue(UNITAI_ATTACK_AIR, this, &eBestAttackAircraft);

						int iAircraftHave = kPlayer.AI_getNumAIUnits(UNITAI_ATTACK_AIR) + kPlayer.AI_getNumAIUnits(UNITAI_DEFENSE_AIR) + kPlayer.AI_getNumAIUnits(UNITAI_MISSILE_AIR);
						int iAircraftNeed = (2 + kPlayer.getNumCities() * (3 * GC.getUnitInfo(eBestAttackAircraft).getAirCombat())) / (2 * std::max(1, GC.getGame().getBestLandUnitCombat()));

						UnitTypeWeightArray airUnitTypes;
						airUnitTypes.push_back(std::make_pair(UNITAI_ATTACK_AIR, 60));
						airUnitTypes.push_back(std::make_pair(UNITAI_DEFENSE_AIR, 100));
						
						if ((iAircraftHave * 2 < iAircraftNeed) && (getCitySorenRandNum(2, "AI train escort sea") == 0))
						{
							if (AI_chooseLeastRepresentedUnit("rebel air units", airUnitTypes))
							{
								return;
							}
						}
					}
				}

				if( bLandWar || bDanger )
				{
					if (AI_chooseLeastRepresentedUnit("rebel offense units", rebelOffenseTypes))
					{
						return;
					}
				}

				if( bAssault )
				{
					if( pWaterArea != NULL )
					{
						UnitTypes eBestAssaultUnit = NO_UNIT;  
						kPlayer.AI_bestCityUnitAIValue(UNITAI_ASSAULT_SEA, this, &eBestAssaultUnit);
						int iBestSeaAssaultCapacity = 0;
						if (eBestAssaultUnit != NO_UNIT)
						{
							iBestSeaAssaultCapacity = GC.getUnitInfo(eBestAssaultUnit).getCargoSpace();
						}

						if( iBestSeaAssaultCapacity > 0 )
						{
							int iUnitsToTransport = kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_ATTACK_CITY);
							iUnitsToTransport += kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_ATTACK);
							iUnitsToTransport += kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_COUNTER);
							
							int iLocalTransports = kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_ASSAULT_SEA);
							int iTransportsAtSea = kPlayer.AI_totalAreaUnitAIs(pWaterArea, UNITAI_ASSAULT_SEA);
							int iTransports = iLocalTransports + iTransportsAtSea;

							int iEscorts = kPlayer.AI_totalAreaUnitAIs(pArea, UNITAI_ESCORT_SEA);
							iEscorts += kPlayer.AI_totalAreaUnitAIs(pWaterArea, UNITAI_ESCORT_SEA);

							// Escorts
							if ((iEscorts < ((1 + 2 * iTransports) / 3)) && (getCitySorenRandNum(2, "AI train escort sea") == 0))
							{
								if ( AI_chooseBuilding(BUILDINGFOCUS_DOMAINSEA) )
								{
									return;
								}

								if (AI_chooseUnit("rebel sea escorts", UNITAI_ESCORT_SEA))
								{
									return;
								}
							}

							// Transports
							if (iUnitsToTransport > (iTransports * iBestSeaAssaultCapacity))
							{
								if ( AI_chooseBuilding(BUILDINGFOCUS_DOMAINSEA) )
								{
									return;
								}

								if (AI_chooseUnit("rebel sea assault", UNITAI_ASSAULT_SEA))
								{
									return;
								}
							}

							// Attack troops
							if( iUnitsToTransport < ((iLocalTransports + (bPrimaryArea ? iTransportsAtSea/2 : 0))*iBestSeaAssaultCapacity) )
							{
								if (AI_chooseLeastRepresentedUnit("rebel offensive units", rebelOffenseTypes))
								{
									return;
								}
							}
						}
					}
				}

				if (AI_chooseUnit("rebel last resort"))
				{
					return;
				}
			}			
		}

		// Buildings important for rebels
		if ((getPopulation() > 3) && (getCommerceRate(COMMERCE_CULTURE) == 0))
		{
			if (AI_chooseBuilding(BUILDINGFOCUS_CULTURE, 30))
			{
				return;
			}
		}

		if( getPopulation() < 8 )
		{
			if (AI_chooseBuilding(BUILDINGFOCUS_FOOD))
			{
				return;
			}
		}

		// Happiness?  Health?  

		int iRebelFlags = 0;
		iRebelFlags |= BUILDINGFOCUS_CULTURE;
		iRebelFlags |= BUILDINGFOCUS_PRODUCTION;
		iRebelFlags |= BUILDINGFOCUS_EXPERIENCE;
		iRebelFlags |= BUILDINGFOCUS_DEFENSE;

		if (AI_chooseBuilding(iRebelFlags))
		{
			return;
		}

		//essential economic builds
		if (AI_chooseBuilding(iEconomyFlags, 10, (25*iEcononmyFlagsThreasholdWeighting)/100))
		{
			return;
		}

		// If nothing special to build, continue to regular logic
	}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/

	if (isOccupation())
	{
		// pick granary or lighthouse, any duration
		if (AI_chooseBuilding(BUILDINGFOCUS_FOOD))
		{
			return;
		}

		// try picking forge, etc, any duration
		if (AI_chooseBuilding(BUILDINGFOCUS_PRODUCTION))
		{
			return;
		}
		
		// just pick any building, any duration
		if (AI_chooseBuilding())
		{
			return;
		}
	}

I'm compiling and testing the new 'mousetrap' now.

Very nice, looks like it works, many thanx. I tested it and the AI directly builded something next turn and all AI civs now have production, also if i give them a new tech they change then to build a usefull building form the meager stuff. Looks really good. Continuing my test game in scenario thread. :goodjob:
 
8953 Jade Death Mask building is a normal building, but has the star like a National or World building.

Also a long standing bug I can't really pin down: there is a period in the early game I can't place wine imprpovement, between plant picking and a true winery. Same for chopping jungles, at the start chopping works, then it doesn't, and after iron working it works again.

It's because Fruit picker becomes obsolete with Orchards but Winery requires Fermentation.

Item 1) I suppose that would be a wonder changed to a normal building after the art was done. @Sparth: take note.

Item 2) Answered by climat. @DH: what do you think we should do with that?

Item 3) I suppose there's something similar taking place with 'slash and burn' as an action going obsolete when forests can be chopped but jungles need to then wait for iron working to be also choppable. @DH: again... what do you think of this?
 
In this game, as soon as I use the Ornithopter to investigate undiscovered territory, the game crashes.
After a thorough diagnosis effort I can say with some confidence that the problem taking place here is in the Ornithopter animation. It appears to be lacking a defined animation for MISSION_RECON. It also looks to be missing an animation for MISSION_AIRBOMB as both have now been attempted. It's also possible I'm misreading the error message and its just simply flawed in these animations and not lacking them entirely. But something is missing in there.

It's not a specific issue to a plot since I can get the crash to take place on the recon mission anywhere it targets.

The solution, for now, has been to disable animation for this mission in the dll. If anyone does plan to solve it from that end, I should be told when the effort will begin so that I can recompile a dll that doesn't turn off the animation. In the meantime, all recon missions will take place fine but the flyover the unit does won't be shown. It's a little eerie now that I've been used to seeing the flyby.
 
8953 Jade Death Mask building is a normal building, but has the star like a National or World building.

It is a world wonder or should be. I am looking into how we can make some of these trade producing buildings act like single nation buildings but have not figured that out. Maybe one of my trials got put on the SVN by accident.

Also a long standing bug I can't really pin down: there is a period in the early game I can't place wine improvement, between plant picking and a true winery. Same for chopping jungles, at the start chopping works, then it doesn't, and after iron working it works again.

It's because Fruit picker becomes obsolete with Orchards but Winery requires Fermentation.

Which is probably why I could never reproduce the problem. My usual path through the tech tree has those two very close to each other.
Also a long standing bug I can't really pin down: there is a period in the early game I can't place wine imprpovement, between plant picking and a true winery. Same for chopping jungles, at the start chopping works, then it doesn't, and after iron working it works again.

Item 1) I suppose that would be a wonder changed to a normal building after the art was done. @Sparth: take note.

Item 2) Answered by climat. @DH: what do you think we should do with that?

Item 3) I suppose there's something similar taking place with 'slash and burn' as an action going obsolete when forests can be chopped but jungles need to then wait for iron working to be also choppable. @DH: again... what do you think of this?

1) should be a world wonder

2-3 should be fixed. BTS has the "chopping" happening at bronze working for both forest and jungle. We would need to split it into two.

We really need a way to obsolete improvement builds.
 
3) Chopping at forests and at jungles has differed so long I thought it was done this way in BtS vanilla. That said, I suspect that slash/burn is obsoleting at the point that forest chopping is enabled so as to avoid confusion between the two. I suppose you're suggesting we could have a slash/burn for each so that they can each obsolete at the right timing.

Not sure what you mean by obsoleting improvement builds. Can't builds be obsoleted already? Isn't that the source of the issue we're talking about here?
 
It is a RoM thing;) Yes it is that old.

FYI With improvements we have three files.

The improvements file describes the improvement, what it requires and how it upgrades. It identifies the terrain that is valid for the improvement.

The builds file describes when you can do this type of build, what improvement it does, the effects of the terrain feature on the build time and what happens when done, eg unit consumed :hammers: produced.

The unit file describes which builds a unit can do.

We have the problem with all the improvement builds in that the obsolete ones show up even after you have built the better improvement on the plot. Currently the only way to obsolete them now is buy not having them on the upgraded workers.

I don't have a copy of Civ here but the modiki here indicates there is no obsolete on the builds file. We don't want the improvement to go obsolete just the worker action so that they can only build the newer.

I have not had my coffee yet this morning so I hope that is clear enough;)
 
Which one is need?? I have one from R2R from the last update they did.

Unfortunately, this doesn't go far enough back. There's the elmination of some of the combat mod stuff, yes, but that's not the problem. The problem is that some critical elements of the updateStackCombat function were accidentally deleted when the combat mod stuff was being developed early on. Unfortunately, where the 'magic' happens for that feature is still not present in the CvUnit.cpp you gave me here. I could update it to current material, sure, but it would end up being the same as not running the stack attack option on bug at all. I need that original part that was deleted and that goes back before R2R.

My first real hint I was working with something too recent was that viewport references were included in the coding. This mistake happened long before viewports.

@Joe: Happen to have an earlier CvUnit.cpp?
 
Unfortunately, this doesn't go far enough back. There's the elmination of some of the combat mod stuff, yes, but that's not the problem. The problem is that some critical elements of the updateStackCombat function were accidentally deleted when the combat mod stuff was being developed early on. Unfortunately, where the 'magic' happens for that feature is still not present in the CvUnit.cpp you gave me here. I could update it to current material, sure, but it would end up being the same as not running the stack attack option on bug at all. I need that original part that was deleted and that goes back before R2R.

My first real hint I was working with something too recent was that viewport references were included in the coding. This mistake happened long before viewports.

@Joe: Happen to have an earlier CvUnit.cpp?

Can you extract that file from old dll's?
 
For reference: Viewports were introduced in SVN 3034, immediately after V24. It seems the SVN started with V13. CvUnit.cpp was added in SVN 5 in 2011-07.

To find all changes that were made to a file you can use the oddly named blame command. Open the svn log, find a revision that changed the file, right-click the file, choose blame..., wait a few minutes.
 
Status
Not open for further replies.
Back
Top Bottom