Understanding Flavors (AICityStrategy)

ww2commander

Emperor
Joined
Aug 23, 2003
Messages
1,243
Location
Australia
This thread is not a tutorial, but a spot I thought I would park some of my findings on the flavor system. I am good at lua but hopeless at C++, so my understanding of the DLL files is very basic and I mostly go off comments in the cpp files. I have limited my exploration to one file so far to keep things easy and not overload myself. The below info is extracted from CvCityStrategyAI.ccp


(Focusing on AICityStrategies.xml) From what I can tell, when a new turn is triggered the AI loops through each player's cities and checks against each strategy listed in the above table and if the city meets the criteria for that strategy then it will add additional weighting to the flavor for that strategy (or nullify it if avoiding the strategy...such as making naval flavors negative for landlocked cities).

Example:
The strategy AICITYSTRATEGY_TINY_CITY places a flavor weight of 10 for FLAVOR_GROWTH. Looking at the C++ code, any city that is less than 2 pop is classed as 'tiny'.


Thus a pop 1 city will return 'true' against this strategy placing a weighting of 10 on FLAVOR_GROWTH. Looking at the other values in the table, it also tells the AI to place much less emphasis (negative values) for FLAVOR_OFFENSE, NAVAL, NAVAL_RECON, HAPPINESS and so on...

Now the AI will go and check units, buildings, processes and projects to build. However, what it will do is increase the weight by 10 for any of the above build types if the flavor is FLAVOR_GROWTH. It will also place negative weighting on the things it needs to ignore, thus filtering its options further.

I am a bit fuzzy on how it chooses between the four build types, but I gather the priority is given to the highest of the four when applying the weight factor.


From my limited testing, it seems we can also add our own checks against cities and focus the AI on specific flavor choices. This is done via GameEvents.CityStrategyCanActivate(AICityStrategyID, playerID, cityID). This game event returns true/false based on the rules you provide for it to check.

Lets say we want the AI to focus more on offense warfare if the city is over 20 pop We would do the following:

Step 1: We add a new strategy (The DLL code explains what the additional values do for those curious)
Code:
INSERT INTO "AICityStrategies" (Type, CheckTriggerTurnCount, MinimumNumTurnsExecuted, WeightThreshold, NoMinorCivs, Permanent) VALUES ('AICITYSTRATEGY_GO_OFFENSIVE', 5, 5, 0, 0, 0);

Step 2: Define the AI city strategy flavors. In this case we ramp up the weighting on FLAVOR_OFFENSE and tell it to focus less on FLAVOR_DEFENSE)
Code:
INSERT INTO "AICityStrategy_Flavors" (AICityStrategyType, FlavorType, Flavor)
SELECT 'AICITYSTRATEGY_GO_OFFENSIVE', 'FLAVOR_OFFENSE', 100 UNION ALL
SELECT 'AICITYSTRATEGY_GO_OFFENSIVE', 'FLAVOR_DEFENSE', -10 ;

Step 3: We need to tell the game to check the condition to trigger this strategy
Code:
function GoOffensive(AICityStrategyID, playerID, cityID)
	if GameInfo.AICityStrategies[AICityStrategyID].Type ~= 'AICITYSTRATEGY_GO_OFFENSIVE' then
		return false -- We only want to test against AICITYSTRATEGY_GO_OFFENSIVE
	else
		local player = Players[playerID]
		local city = player:GetCityByID(cityID)
		local cityPop = city:GetPopulation()

		if cityPop > 20 then -- Is this city's pop greater than 20?
			return true -- Yes
		else
			return false -- No
		end
	end
end

Step 4: We add a listener for the event which will trigger each turn
Code:
GameEvents.CityStrategyCanActivate.Add( GoOffensive )

Now, when the game processes AI player cities, it will test against the above function. If it finds a city with a pop over 20 it will add a weighting of 100 to any units, buildings, processes or projects with FLAVOR_OFFENSE.

I assume (yet to check) that the same logic applies to all the other AI strategy tables and that with a bit (maybe a lot) of effort, the AI can be 'nudged' more firmly into certain directions based on your mod needs.

Please add or correct me as required. Hopefully this helps people understand flavors and opens up the lid a bit more on the AI.
 
Code:
			bool bStrategyShouldBeActive = false;
				...
				// Check Lua hook
				ICvEngineScriptSystem1* pkScriptSystem = gDLL->GetScriptSystem();
				if(pkScriptSystem && [B]bStrategyShouldBeActive[/B])

You still need DLL code, because it won't call your function unless something has set bStrategyShouldBeActive to true.
 
I guess that's the part where some experience in reading C++ could come in handy.

Dang went an got me' self all excited for nothing :(

EDIT: On the other hand, we could still use the functionality if we 'hooked' into one of the other strategies such as AICITYSTRATEGY_RIVER_CITY. This way you could trigger your strategy for river cities along with the base strategy.
 
Back
Top Bottom