September 20th, 2017, 01:54
Posts: 542
Threads: 4
Joined: Jul 2017
Wow, that sounds painful. I mean the whole thing, having to care about allocated space haha, not been doing that in perhaps 20 years :D
You are the boss!
September 20th, 2017, 12:03
(This post was last modified: September 20th, 2017, 12:05 by Seravy.)
Posts: 10,492
Threads: 395
Joined: Aug 2015
The bad news : I tried allocating more memory but couldn't. The game probably uses all of it, or the data structures that store the allocated pages are limited and can't handle more.
The good news : For some reason whoever distributed the allocated memory between the various AI arrays seems to have thought 1 segment address = 8 offset address when it's 16. So everything allocated is twice as big as it should be, at the very least the target matrix definitely is.
So...we already have the space we need allocated. I even peeked into the memory and the extra space is full of zeroes - it appears unused.
Unless there is some trick here I don't know about? I don't see any uses of the second half of the array anywhere.
...so now I need to code the entire new system using that space and see if it works. This will probably take a full day.
September 20th, 2017, 15:33
Posts: 10,492
Threads: 395
Joined: Aug 2015
I've just seen 2 War Bears lose to a lair with 7 phantom warriors. Bears have a total rating about 7 times a Phantom Warrior so they should have won based on that - bears are 2x stronger but...
Lair : 2702 attack, 770 defense (~2 million)
Bears : 792 attack, 1496 defense. (~1 million)
This shows the lair is about twice as strong if you multiply the numbers
Where is the difference coming from?
Math.
The problem is, the strength of a unit is A*D - their attack*defense.
The strength of an army in combat is, well, also A*D, roughly - it does A damage and lives D duration so same, damage output is proportional to attack*defense.
But, problem.
AI overland (and in combat) Army strength is the sum of the individual unit strengths - it's calculated per unit, not per army.
So we have (A1+A2+A3+A4)*(D1+D2+D3+D4) as their cumulative army power - this is how well they'll actually perform in combat.
On the other hand, the sum power of the 4 units is (A1*D1)+(A2*D2)+(A3*D3)+(A4+D4).
And those two are not equivalent, the former is always higher than the latter and this gap increases as the number of units grow. So stacks with fewer units in them will be overrated by the AI.
A simple example.
If I have 2 bears against 1 bear, I'm 4 times as powerful in strategic combat - I have both double attack power and durability. At 3 against 1, I'm 9 times as powerful, and so on. X times more units is X^2 times the power.
But the AI sums the numbers for all decisions. So it considers X times more units X times more powerful instead.
The problem? There is no way to make the AI sum attack and defense on different units first then multiply to get the accurate result. But this just made me realize the "Accurate" formula is still horribly inaccurate.
In normal combat, armor mitigates this inaccuracy - more, smaller units will deal less damage through armor. But in strategic combat, there is no such effect. So 7 swordsmen will overwhelm 2 bears - even though the sum of their individual power is half, their power together is double.
No idea if we can do anything about this unless we change strategic combat rules. (also this might explain why the AI is so effective when it goes 9 vs 4 on stronger defending units)
September 20th, 2017, 15:50
(This post was last modified: September 20th, 2017, 15:52 by Seravy.)
Posts: 10,492
Threads: 395
Joined: Aug 2015
I guess the only good idea I have for this is to make sure the AI always aims at having an advantage when targeting lairs. Against human players it's normal combat so it's less relevant. Against other AI, well, if it was correct then the other AI would attack this AI instead. Also their relevant stacks will almost always have many units on both sides - no one cares if a 2 vs 9 battle results in losing the 2 units.
Alternately we can force the AI to require proportionally larger advantage if the number of attackers is small...
September 20th, 2017, 16:23
(This post was last modified: September 20th, 2017, 16:24 by Nelphine.)
Posts: 5,010
Threads: 17
Joined: Aug 2016
Oh I thought it looked at stack value, not at sum of units value. Blech. So there's no way for the AI to see the strength of a tile, instead of looking at a tile and seeing unit a then unit b then unit c etc?
Ugh. This is exactly where I wish I understood the coding.
September 20th, 2017, 16:53
(This post was last modified: September 20th, 2017, 16:54 by Seravy.)
Posts: 10,492
Threads: 395
Joined: Aug 2015
The code is pretty much this :
for each unit on tile, tilepower=tilepower+unitpower(unit)
Instead we'd need
{ for each unit on tile, { tiledefense=tiledefense+unitdefense(unit); tileattack=tileattack+unitattack(unit) }
tilepower = tiledefense*tileattack
}
So basically, we'd need to throw away the unit rating altogether, and use defense and attack individually, everywhere which is like, a dozen of places. Not very doable and the problem is, in normal combat the current system is probably more accurate.
So this is the workaround I'm considering to test :
Quote:-AI intercontinental attacks performed by 4 or fewer units require twice as much army power as normally sized stacks, 2 or fewer units require 4 times the power
-AI land attacks performed by 4 or fewer units require twice as much army power as normally sized stacks, 2 or fewer units require 4 times the power
From what I see, the difference between the two calculations seems to be the ratio of the number of units on sides.
Assuming all stats equal, one is X*(A*B) while the other is (X*A)*(X*B) for X units so exactly X times more.
If the attacking stack needs to be at least 5 units then the inaccuracy is kept below 100%. If it's at least 3, then the inaccuracy could be 200% but if we halve the stack power it drops to 50%. At 1 unit the worst is 800% but dividing by 4 cuts it to a more realistic 125%. This still means in worst case the AI will be overwhelmed by twice the force, but that much difference can be overcome by lucky rolls, spells, or negated by other inaccuracies.
The downside, the AI will be less willing to throw their small stacks against weaker, even smaller targets - but that's not always a bad thing. Those units eventually get included in a larger stack and become part of a more relevant attack if they fail to do so on their own. What's more terrifying, 2 sprites attacking your first new city...or 5 of them doing it a few turns later?
(also, less small battles means less chances for the AI to waste mana on meaningless fights - easy to spend 1000 mana on a zombie vs halberdier battle...)
This even scales well - 1 Great Drake is powerful but easy to kill with fire bolts if kited. If it's hesitant to attack my 3 great lizards, I'm in a bigger trouble.
The only problem, it makes the AI more vulnerable to Flame Strike and Massacre - but this is hardly relevant because against those realms, an attack using 1-3 units is an even worse idea due to their powerful single target spells.
September 20th, 2017, 17:02
Posts: 5,010
Threads: 17
Joined: Aug 2016
How do you calculate unitpower? Can we change that formula without having to do so in a lot of places? (For instance, if it is just unit attack * unit defense, can you make it [unit attack * unit defense]^(1/2)?
September 20th, 2017, 17:29
Posts: 10,492
Threads: 395
Joined: Aug 2015
I can but that doesn't make a difference, does it?
Let me see...
On one side we'd get X*SQRT(A*B).
On the other we'd get (X*A)*(X*B) which is (X^2)*(A*B).
That just made it worse.
Ok, I can prove we can't fix this that way.
We've already proven the difference between the two is a multiplier of X = the number of units in the stack.
X is external to unit ratings - the rating of the unit cannot depend on the size of the stack its inside of otherwise it's not longer the unit's rating. (also it's literally not possible because X is not known in the procedure anyway)
In fact, if unit rating was X*A*B everything would be perfect. But we don't have that X there. And what's worse, we don't even know it outside. You see, a "stack" is just 5 random units in an array of 2000 units that have the same coordinates as the map tile. You don't know how many there are until you find them all. But when you find one, you calculate the rating for it immediately without knowing how many you'll find later - otherwise you'd need a second array to store the unit for future processing. That not only doubles the code size (two loops instead of one) but also requires a new array - fortunately the limit if 9 units so that could be a local stack variable, but double the code size in many different locations, nah.
And it's even worse. Just because there are 9 units on a tile doesn't mean 9 units will be attacking...some of them might not be intercontinental and might be left behind. This isn't known until the attack procedure - and there you can't call unit ratings because it crashes.
Either way, I finished implementing the "Big" feature :
Quote:-New AI overland intercontinental attack procedure - now uses real unit ratings instead of simplified and might even process faster.
So two things.
One, I'm going to sleep now and just finished an entire game on Expert so don't feel playing right now anyway. Please test the new attack system and tell me if it behaves correctly - I did watch the AI play a few dozen turns and it looked alright.
Second - as this procedure already has targets for the entire map pre-marked, the "distance of 10" limitation is no longer necessary.
Question is, do we want to keep it, change the distance, or remove it.
Note that if removed, that means the AI will send its stack of 2 sprites against a single spearmen 30 tiles away which might massively interfere with doomstack creation.
On the other hand it also makes sure that doomstack will find its way to any unopened lair on the map even if it's not on the main action continent.
The file is "Wizards14beta", as I prefer not to release this as an "experimental" with only this much testing and there are more, smaller changes still pending (including Nature's Wrath if we manage to decide on the effect)
September 21st, 2017, 03:24
Posts: 542
Threads: 4
Joined: Jul 2017
Pushing the AI further away from its fortress exacerbates "unfairness" type issues linked with the lack of need to scout, and the troops randomly running around. I'd be against.
Two questions on strategic combat:
1. does it ever end in a draw? Or does stuff like sprites fight in melee in strategic?
2. does the initial strategic ranged combat phase also split damage among all the troops?
September 21st, 2017, 03:32
Posts: 10,492
Threads: 395
Joined: Aug 2015
1. Yes but it's rare. Ranged armies do fight in melee once the ranged turns are exhausted. So for a draw both armies need to mutually destroy each other completely.
2. It adds to the total damage to be split at the end of the battle. During battle, damage dealt isn't dealt to individual units but does decrease the attack and defense ratings of the armies proportionally to simulate the "dead" figures/units.
|