Check out the guide on formations in my signature – it has a section about AI behavior on the battlefield.
The formula itself looked something like this (FV - Fight Value from crtraits.txt):
K_stack = HP_unit * (stack_damage / FV_unit), where
FV_unit = sqrt(((FV_base + (hero_attack * FV_base) / 20)^2) * ((FV_base + (hero_defense * FV_base) / 20)^2))
However, this isn't quite everything, but it's an approximate explanation of how the stack simply wants to deal more damage, not just to HP, but to HP * FV, and it also takes into account the hero's attack and defense separately. That is, all other things being equal, a stack with 5/5 attack and defense and a hero with 0/0 is not the same as 3/3 and 2/2, even though the damage is the same. At the same time, the wyverns always flew in if the ratio (K_stack_dwarves / K_stack_wyverns) >= 2. That is, they were already resigning themselves to defeat. Also, if the ratio <= 0.07, they consider that they have already won.
I can describe all this based on my old notes, but it's quite possible that I'm wrong about something; after all, it's been almost a year. If you're interested, I can show you examples of calculations and everything, but I'd have to refresh my memory.
In practice, this translates to: attacking harpies in hives, attacking archers at the beginning of the round against the advanced units, not against elves, the fear of getting hit by a stack of wyverns, and attacking with a single unit.
P.S. And yes, by the way, stack_damage is the average damage. That is, a stack of air units will calculate its damage as 5 with a damage range of 2-8. At one point, I wanted to record a video with the formula displayed, but I was just too lazy.