What does 'SetDeployFromOperationTurn' and 'AddTemporaryDominanceZone' actually do?

ww2commander

Emperor
Joined
Aug 23, 2003
Messages
1,243
Location
Australia
Now that we have the DLL, can anyone with an understanding of C++ provide an explanation as to what these two functions are supposed to do when used by the AI.

I noticed they go together but have never figured it out from the LUA examples I have seen as to their purpose!
 
No one can provide any feedback?

Would really appreciate it as I am trying to figure out ways to get the AI to attack in specific directions/objectives and was hoping this might be the holy grail.
 
From the code, it doesn't *obviously* do anything

The Lua sets a Temporary Zone of AI_TACTICAL_TARGET_CITY

Code:
int CvLuaPlayer::lAddTemporaryDominanceZone(lua_State* L)
{
	// Notify tactical AI to focus on this area
	CvTemporaryZone zone;
	zone.SetX(iX);
	zone.SetY(iY);
	zone.SetTargetType(AI_TACTICAL_TARGET_CITY);
	zone.SetLastTurn(GC.getGame().getGameTurn() + GC.getAI_TACTICAL_MAP_TEMP_ZONE_TURNS());
	pkPlayer->GetTacticalAI()->AddTemporaryZone(zone);
}

but the code that processes zones explicitly ignores those

Code:
pZone = pTacticalAI->GetFirstTemporaryZone();
while(pZone)
{
	// Can't be a city zone (which is just used to boost priority but not establish a new zone)
	if(pZone->GetTargetType() != AI_TACTICAL_TARGET_CITY)
	{
		// SNIP!
	}

	pZone = pTacticalAI->GetNextTemporaryZone();
}

But it *must* do something, as Firaxis use it a lot in their own scenarios (unless it's seriously buggy), so the effect must be non-obvious in other spaghetti code
 
Crud....I was hoping it would be the holy grail to sending spawned units to a specific area or city and getting them to attack or maintain presence for x amount of turns. :(

This would really have helped with my WWII Eastern Front scenario.
 
AddTemporaryDominanceZone:

I think it simply causes the AI to focus more on capturing this city. The plot should probably be a city even if I don't think it's required. (see CvTacticalAI::IsTemporaryZoneCity and the functions that call it.)


SetDeployFromOperationTurn:

This appears to be used to decide if the unit is helping attacking/controlling a zone or if it's available for other things. It is used in combination with the AI_TACTICAL_MAP_TEMP_ZONE_TURNS xml define.

If the current turn # is higher than GetDeployFromOperationTurn + AI_TACTICAL_MAP_TEMP_ZONE_TURNS (default 5) then we consider the unit available for other things. Otherwise it's busy with zone control.
I'm not sure what happens if the unit is considered helping control zones but is too far from any to do so.
 
Thanks snarko. This info helps as it gives me something to go off when running some tests.

The main issue I am having in my scenario is that the AI will pull off atleast half its units from the front line early in the game so that they can go back home! I tried giving cities some defending units but the AI still decides to extract units from the frontline.

This issue is worse when scripted events such as Italian forces arriving on the frontline. The AI gets 7 units at a specific turn and decides to send 5 back home instead of attacking! :twitch:
 
Thanks snarko. This info helps as it gives me something to go off when running some tests.

The main issue I am having in my scenario is that the AI will pull off atleast half its units from the front line early in the game so that they can go back home! I tried giving cities some defending units but the AI still decides to extract units from the frontline.

This issue is worse when scripted events such as Italian forces arriving on the frontline. The AI gets 7 units at a specific turn and decides to send 5 back home instead of attacking! :twitch:
Have you tried to lower the AI_STRATEGY_MILITARY_RESERVE_PERCENTAGE define ?(default is 35, try 20 or less)
 
Craig - Will do so if anything meaningful comes out of my testing.

Gedemon - Thanks for the heads-up on this define. The thing that annoys me is I don't have a clue what half those defines do and the document on them is very sparse.

It would be good if someone eventually did a DLL discovery thread on the AI_STRATEGY and AI_TACTICAL defines and explain briefly what each one actually does.

Will try your suggestion tonight and see what the outcomes is.
 
One option I noticed might work is the AI_PLOT_VALUE_STRATEGIC_RESOURCE define.

I raised this to 100 and noticed that the AI was more aggressive towards areas with my mines and oil fields in the limited testing I did.

I could be going crazy...and thus I was hoping one of you DLL gurus might be able to confirm if the define value making the AI focus more on capturing strategic resource plots.
 
Sorry, all increasing that value does is make the AI prioritize buying plots with strategic resources more.
 
:wallbash:

I give up tinkering with stuff I have no clue about.

Does anyone else have any ideas on how to make the AI aggressive in a specific area?
 
JUst an update from my play testing observations....

In my scenario, I have setup lua rules that trigger when an enemy city is captured and generates more units for the AI.When creating the units, I ensure the above functions are set as a part of the process.

What I have observed is that the majority of the units (6/8 of 10) tend to go for the enemy city area, but a small amount will rush off to another direction near the designated plot. However, in a few games, most of the stragglers shift direction and reform with their 'siblings' as soon as the first lot have entered near the plot area!

Not sure if this behaviour is indeed in line with code in the DLL or if it simply coincidence based on my map?

The key example I focus on is how the German forces in my scenario capture Sevastopol (which if any of you are aware, sits on its own in the Crimean peninsula). Most of the units approach it whilst a few shoot off towards Rostov/Stalingrad direction. But when the units from the spawned group enter near Sevastopol, the othremaining spawned units shoot in reverse and support the units laying seige to the city.


Some additional points:

- All my units (USSR) are fortified to prevent movement. This to ensure I see how the AI flows and chooses its direction of attack. Is it going around with no purpose or actually attacking properly? Luckily the answer is the later.

- The AI already has 100+ ground units when the scenario kicks off. Irrespective of other units in the area, the AI does seem to specifically send these spawned units in the proper direction and 'control' or attack the zone. This does not mean that other units do not also assist. I notice that the Romanian civ units always support the German ones in the area in proper ingame allied form.

Has anyone had any similar visual examples to confirm I am not going crazy with the above observations?

EDIT: Just to provide info on my original concern with the AI shifting its units back.....it turns out that the traffic jam on the German/USSR frontline (in Poland area) when the scenario begins forces the AI to look for another way around. Unfortunately the mountain range in Hungary/Romania blocks this path for most units thus forcing the German units to go around via Yugoslavia > Romania and then back into USSR territory. Thus no concern about a lack of aggression :)
 
Could you post that snippet of code please. I'd like to do something similar with my mod, but rather than reinventing the wheel...

In my mod, I want to spawn a viking attack fleet and send it to take over a certain area. Hopefully, non-spawned units will join in as they seem to do in your mod. Simple forced DOWs don't seem to do the trick.

Thanks.
 
No problems....here is a snippet of the relevant code.

The function call GetValidSpawnPlot is simply whoward's iteration code which basically takes a plot and then checks x amount of tiles around it for valid empty plots that the unit can be spawned on. I do this to ensure I get no funny results or CTD!

Key code sections in red for your reference.

dominanceZonePlot is a plot values x,y

Code:
function GenerateBonusForce(player, spawnPlot, dominanceZonePlot)

	local plot, validPlot
	local includeCentrePlot = false	-- Exclude centre plot

	plot, validPlot = GetValidSpawnPlot(player, spawnPlot, 5, SECTOR_NORTHEAST, includeCentrePlot )
	if validPlot then
		[COLOR="Red"]local unit = InitNewUnit(player, UNIT_GER_TANK_EARLY2, plot:GetX(), plot:GetY())[/COLOR]
		[COLOR="Red"]unit:SetDeployFromOperationTurn(1)[/COLOR]
		Dprint(unit:GetName().." successfully created as part of 'city capture' bonus for Germany at "..plot:GetX()..","..plot:GetY())
	else
		Dprint("Failed to find an unoccupied plot for creating 'city capture' bonus unit for Germany. Skipping it!")
	end

	[COLOR="Red"]player:AddTemporaryDominanceZone (dominanceZonePlot)[/COLOR]

end
 
I've been fiddling with this function. I am trying to use it with non-spawned units. I've created the following code, but nothing seems to be happening.

Code:
function HladirAttackOnBamborough()
	
if Game.GetGameTurn() == 0 then

	--set Hladir as player
	local pHladir
	
	for iPlayer=0, GameDefines.MAX_MAJOR_CIVS-1 do 

		local pHladir = Players[iPlayer]
	
		if (pHladir:IsAlive() and not pHladir:IsHuman()) then
			if (GameInfo.Civilizations.CIVILIZATION_SONGHAI.ID == pHladir:GetCivilizationType()) then
			
			-- loop through Hladir units and find units based on combat type

			--local unit = unit:GetID()

			for unit in pHladir:Units() do				
			
			if (unit:GetUnitCombatType() == 1) and (Game.Rand(100, "Selecting attack unit") < 50) then
				unit:SetDeployFromOperationTurn(1);
			elseif (unit:GetUnitCombatType() == 2) and (Game.Rand(100, "Selecting attack unit") < 50) then
				unit:SetDeployFromOperationTurn(1);
			elseif (unit:GetUnitCombatType() == 3) and (Game.Rand(100, "Selecting attack unit") < 50) then
				unit:SetDeployFromOperationTurn(1);
			elseif (unit:GetUnitCombatType() == 4) and (Game.Rand(100, "Selecting attack unit") < 50) then
				unit:SetDeployFromOperationTurn(1);
			elseif (unit:GetUnitCombatType() == 11) and (Game.Rand(100, "Selecting attack unit") < 50) then
				unit:SetDeployFromOperationTurn(1);

			-- select half of those units			
			
			--if (Game.Rand(100, "Selecting attack unit") < 50) then

			-- add that unit to operation
						
				--unit:SetDeployFromOperationTurn(1);
							
			Players[iPlayer]:AddTemporaryDominanceZone (53, 48);

			--end
			end
			end			
		end
		end
	end
end
end

Events.ActivePlayerTurnEnd.Add(HladirAttackOnBamborough)

There are a few things that might not be correct though...

1) The hex for AddTemporaryDominance is unexplored and this affects the AI.
2) My coding sequence is flawed and what I want to happen is not happening as I expect (ie. my elseif statements are used incorrectly).
3) I am misusing Game.Rand, and it is not firing off as i expect.

and finally,

4) The function only works for spawned units.

The lua shows no errors, but that does not necessarily mean anything.

I hope that no. 4 is not the case as I'd prefer not to give free units to the AI, but rather have them create units in a natural way.

Any ideas? I'll continue in my attempts to get the function to work, but guidance would be appreciated.

(excuse the commented out lines... many are from earlier versions of code that I am not yet ready to throw out.)
 
By the way, Game.Rand has text associated with it... where should I be seeing that? It is not in any log file that I can see.

You need to enable it seperately in config.ini

Code:
; Rand event logging bitfield.  bit 0 = on/off, bit 1 = log callstacks, bit 2 = log pregame calls, bit 3 = log asynchronous RNGs
RandLog = 0

IIRC the value you want is 5
 
Ok, theres a lot to reply to here!
By the way, Game.Rand has text associated with it... where should I be seeing that? It is not in any log file that I can see.
Open up your 'Sid Meier's Civilization V SDK' program (icon with a sledge hammer over some hexes) and select the FireTuner Runtime Lua Console. This will allow you to see any errors and other game messages.

I normally sprinkle my code with print(" ") statements when first testing so I know how far it goes through before it crashes with an error message.

The hex for AddTemporaryDominance is unexplored and this affects the AI.
I think this does affect things as the functions tend to be used by the AI on already explored areas. From memory the AI will fail to carry out missions over unexplored plots as it does not yet know if it is land or water.

Also, I am starting to think the functions are used as a part of the barbarian system as their units tend to spawn around a known encampment plot and then flex dominance around that zone by constantly harassing players.

Code:
			if (unit:GetUnitCombatType() == 1) and (Game.Rand(100, "Selecting attack unit") < 50) then
				unit:SetDeployFromOperationTurn(1);
			elseif (unit:GetUnitCombatType() == 2) and (Game.Rand(100, "Selecting attack unit") < 50) then
				unit:SetDeployFromOperationTurn(1);
			elseif (unit:GetUnitCombatType() == 3) and (Game.Rand(100, "Selecting attack unit") < 50) then
				unit:SetDeployFromOperationTurn(1);
			elseif (unit:GetUnitCombatType() == 4) and (Game.Rand(100, "Selecting attack unit") < 50) then
				unit:SetDeployFromOperationTurn(1);
			elseif (unit:GetUnitCombatType() == 11) and (Game.Rand(100, "Selecting attack unit") < 50) then
				unit:SetDeployFromOperationTurn(1);
The tip I have here is use the global defines already created by the game for combat types (see this). Its much easier to read code that says:
if (unit:GetUnitCombatType() == UNITCOMBAT_ARCHER)
rather then:
if (unit:GetUnitCombatType() == 1)
Trust me its hard enough reading code without having to troubleshoot errors. Make things as 'readable' as possible!

Players[iPlayer]:AddTemporaryDominanceZone (53, 48)
Three things with the above line. First it will only get executed as a part of the last elseif as it sits inside that block only.
Second, ensure you use uniform tabbing in your code. I only noticed that when I fixed the tabbing for the if statements.
Third, you have already defined Players[iPlayer] as pHladir so you can simply write:
pHladir:AddTemporaryDominanceZone (53, 48)
This minimizes the amount of processing lua has to do if things are already declared as a 'local'.

I am misusing Game.Rand, and it is not firing off as i expect.
Unfortunately I have never used this function myself so don't know what to expect. It looks like a random generating function and the examples are similar to yours so I don't think it is the issue.
 
Back
Top Bottom