fa icon indicating copy to clipboard operation
fa copied to clipboard

Use the internal unit statistics

Open Garanas opened this issue 1 year ago • 9 comments

Description of the proposed changes

Remove the tracking of unit statistics. They are unnecessary as the engine tracks the same information.

Testing done on the proposed changes

Launch a game using 2badd4141ef4ee7a26dd6a8a8356311b25ffaffe and compare the results when you exit. You should see something like this in your logs:

INFO: 1	uel0001	0	->	nil -- killed
INFO: 1	uel0001	1	->	nil -- created
INFO: 1	uel0001	1	->	1   -- still alive
INFO: 1	uea0303	0	->	nil
INFO: 1	uea0303	8	->	8
INFO: 1	uea0303	3	->	3
INFO: 1	uel0401	0	->	nil
INFO: 1	uel0401	1	->	1
INFO: 1	uel0401	0	->	nil
INFO: 2	ual0001	0	->	nil
INFO: 2	ual0001	1	->	nil
INFO: 2	ual0001	1	->	1
INFO: 2	uel0001	1	->	1
INFO: 2	uel0001	0	->	nil
INFO: 2	uel0001	0	->	nil
INFO: 2	uea0303	1	->	1
INFO: 2	uea0303	0	->	nil
INFO: 2	uea0303	0	->	nil
INFO: 3	ual0001	1	->	1
INFO: 3	ual0001	0	->	nil
INFO: 3	ual0001	0	->	nil
INFO: 3	xsl0001	1	->	1
INFO: 3	xsl0001	0	->	nil
INFO: 3	xsl0001	0	->	nil
INFO: 3	ura0303	0	->	nil
INFO: 3	ura0303	7	->	7
INFO: 3	ura0303	2	->	2
INFO: 3	xsa0303	7	->	7
INFO: 3	xsa0303	0	->	nil
INFO: 3	xsa0303	0	->	nil
INFO: 3	url0402	0	->	nil
INFO: 3	url0402	1	->	1
INFO: 3	url0402	0	->	nil
INFO: 3	xrl0403	0	->	nil
INFO: 3	xrl0403	1	->	1
INFO: 3	xrl0403	0	->	nil
INFO: 3	xsl0401	2	->	2
INFO: 3	xsl0401	0	->	nil
INFO: 3	xsl0401	0	->	nil
INFO: 4	xsl0001	0	->	nil
INFO: 4	xsl0001	1	->	nil
INFO: 4	xsl0001	1	->	1
INFO: 4	ura0303	2	->	2
INFO: 4	ura0303	0	->	nil
INFO: 4	ura0303	0	->	nil
INFO: 4	uea0303	2	->	2
INFO: 4	uea0303	0	->	nil
INFO: 4	uea0303	0	->	nil
INFO: 4	xsa0303	0	->	2
INFO: 4	xsa0303	6	->	6
INFO: 4	xsa0303	6	->	9
INFO: 4	xsl0401	0	->	nil
INFO: 4	xsl0401	0	->	nil
INFO: 4	xsl0401	0	->	2

Additional context

This was introduced 8 years ago in https://github.com/FAForever/fa/commit/06690e0bf6a6e0bc8ec5d3c48ae8b96a2fa09612. The use of JSON instead of XML is fine, but it appears the introduction of this logic to track the status quo of units was not necessary.

Checklist

  • [ ] Changes are annotated, including comments where useful
  • [ ] Changes are documented in the changelog for the next game version
  • [ ] Keep support for the 'lowest health' ACU achievement

Garanas avatar Apr 27 '24 08:04 Garanas

@relent0r / @maudlin27 These brain functions may also be interesting to you as an AI developer. They make it trivial for you to retrieve various interesting properties. And the properties in question appear to be cached, so it's not re-computed as you go.

For example, these statistics are available:

        LOG("Units_BeingBuilt: ", repr(self.Brain:GetBlueprintStat('Units_BeingBuilt', categories.TECH3)))
        LOG("Units_History: ", repr(self.Brain:GetBlueprintStat('Units_History', categories.ALLUNITS)))
        LOG("Enemies_Killed: ", repr(self.Brain:GetBlueprintStat('Enemies_Killed', categories.ALLUNITS)))
        LOG("Enemies_Lost: ", repr(self.Brain:GetBlueprintStat('Enemies_Lost', categories.ALLUNITS)))
        LOG("Units_TotalDamageDealt: ", repr(self.Brain:GetBlueprintStat('Units_TotalDamageDealt', categories.ALLUNITS)))
        LOG("Units_TotalDamageReceive: ", repr(self.Brain:GetBlueprintStat('Units_TotalDamageReceive', categories.ALLUNITS)))

Example output:

INFO: Units_BeingBuilt: 	1
INFO: Units_History: 	186
INFO: Enemies_Killed: 	15
INFO: Enemies_Lost: 	0
INFO: Units_TotalDamageDealt: 	47671
INFO: Units_TotalDamageReceive: 	77500

Garanas avatar Apr 27 '24 08:04 Garanas

@relent0r I noticed that your AI makes use of the unit data that is stored in the brain. Are you aware of the engine alternatives that allow you to gather data based on categories, for example?

Garanas avatar May 12 '24 10:05 Garanas

@lL1l1 what are your thoughts on replacing the Lua-based statistics tracking with the engine-based statistics tracking? It feels more cohesive and reduces the Lua overhead, even if it is just a little bit

Garanas avatar May 12 '24 10:05 Garanas

@relent0r I noticed that your AI makes use of the unit data that is stored in the brain. Are you aware of the engine alternatives that allow you to gather data based on categories, for example?

Are we talking about the IntelManager unit stats? Just looking at the documentation (that someone was helpful enough to write). I hadn't considered replacing the onkilled callbacks. Looking at the GetArmyStat and GetBlueprintStat together. Do you know if there is a units built mass value based on category? it almost seems like there should be given there is an armystat for it called 'Units_MassValue_Built'.

relent0r avatar May 12 '24 21:05 relent0r

I'll have to experiment more with these two functions to fully understand them, I'll update the documentation and get back to you!

Garanas avatar May 13 '24 10:05 Garanas

I think it's fine to replace the kills/built/lost lua tracking with engine tracking. At worst, apply an __index metamethod to AIBrain.UnitStats["kills"|"built"|"lost"], so we just return the value given by the engine.

That piece of code in sim/score.lua checking unit stats through Lua is something I wrote recently (4 months ago) and is wrong because I didn't think of checking categories.blueprintId at the time. I even had to re-add the "kills" lua tracking in that PR, which makes me doubt that people used those stats if it never got brought up.

lL1l1 avatar May 14 '24 05:05 lL1l1

The economy stats don't seem to function with getBlueprintStat. It returns 0 for everything.

Console script to print all economy stats as used by getBlueprintStat checking all units
SimLua 
local stats = {
'Economy_TotalProduced_Energy',
'Economy_TotalConsumed_Energy',
'Economy_Income_Energy',
'Economy_Output_Energy',
'Economy_Stored_Energy',
'Economy_Reclaimed_Energy',
'Economy_MaxStorage_Energy',
'Economy_PeakStorage_Energy',
'Economy_TotalProduced_Mass',
'Economy_TotalConsumed_Mass',
'Economy_Income_Mass',
'Economy_Output_Mass',
'Economy_Stored_Mass',
'Economy_Reclaimed_Mass',
'Economy_MaxStorage_Mass',
'Economy_PeakStorage_Mass',
}
for i,stat in stats do
LOG(stat, ArmyBrains[GetFocusArmy()]:GetBlueprintStat(stat, categories.ALLUNITS))
end 

lL1l1 avatar May 14 '24 05:05 lL1l1

At worst, apply an __index metamethod to AIBrain.UnitStats["kills"|"built"|"lost"], so we just return the value given by the engine.

This is a good suggestion, as a fallback.

Garanas avatar May 20 '24 14:05 Garanas

@Garanas fyi I'm starting to use these now with my AI. At the moment its just a simple use case of wanting a stat of how many units of a particular category has been built so the AI can build something once and then measure its efficiency before knowing if it should build some more.

I was hoping that the GetBlueprintStat parameters match up with the GetArmyStat parameters, but things like Enemies_MassValue_Destroyed didn't return any non zero values sadly.

Wondering if 4zot has any visibility of whats available in this function.

relent0r avatar Jun 05 '24 19:06 relent0r