Ok, this has definately identified a scaling issue. The time is being consuming in stack attack odds caclulations when one very large stack attacks another very large stack. Basically this is because the odds calculations pretty much simulate a mock battle to assess probable casualties on both sides. In this process, at each stage it has to choose the best attacker, which involves testing each one in turn. For each attacker it then has to select the best defender, so the unit on unit comparisons (which involve taking account of all the promotions etc., so are not just a direct strength number comparison) happen O(N x M) times where N and M are the stack sizes. Furthermore all possible attacks (in a close by area) will be tested, so each large stack is probably involved in several test-battles before a decision is taken on what to actually do. If there are more than 2 large stacks in the area the combinatorics of different stack combinations for different potential target choices will also come in.
Furthermore, the AI remakes its decision for each move, so in the case of a large stack once the top unit has decided it's a good idea and used its turn in the attack, the (rest of) the stack will go through the decision process again, and so on so the entire process is effectively multiplied by the stack size again!
None of this is cached.
In your game there appears a SoD of 65 units attacking an area that has defender stacks of 45 units, 28 units and a few smaller ones.
I should be able to resolve this with some judicious caching.