June 3rd, 2017, 06:33
(This post was last modified: June 3rd, 2017, 07:50 by Nelphine.)
Posts: 5,010
Threads: 17
Joined: Aug 2016
So what I want is
1. Find current stack that has the highest strategic strength that is entirely intercontinental. Skip the fortress stack.
2. Go through every owned unit, disregarding any with a cost less than 55. Skip land units. Skip units with any orders other than idle or move to. Skip units in capital.
3. Put all units into a list of 11. Put all the units from step 1 at the top of the list. Then fill in the list with all other units from step 2, highest cost first. Discard any after the first 11 are determined.
4. If there are less than 9 units, abort.
5. Count the highest number of units out of these 11 on the same tile.
6. If there are already 9 units on the same tile, send them to attack something; treat the target tile as the target and skip to 13 for the rest of the units on the list.
7. If that number is less than 6, skip forward to 11.
8. Check if the shared location is a node or city. If yes, skip to 10.*** (Actually, just skip this step; step 10 includes an attack procedure anyway, so this doesn't matter.)
9. Check if the stack with 6+ units is already ordered to attack something. If yes, treat the target tile as the target and skip to 13 for the rest of the units on the list.
10. Check if any of the remaining units not at the location of those 6 (or more) are within 8 tiles. If not, send the 'ready' doomstack of 6+ units to attack something, and treat their target tile as the target for the rest of the units and skip to step 13 for those units.
11. Calculate the two average positions of the 9 units - one going through the edge of the map, and one not going through.
12. Calculate the total distance of the units from the two calculated points. Pick the one with less distance.
13. Find the closest empty map tile to the selected position. (no nodes, cities, other units of any player - but units already on the list of 9 are ok)
14. Send all units towards that map tile.
Done, and next turn repeat this entire procedure (after resetting all units to idle status and going through all other procedures suck as finding attack targets).
June 3rd, 2017, 06:48
(This post was last modified: June 3rd, 2017, 07:13 by Nelphine.)
Posts: 5,010
Threads: 17
Joined: Aug 2016
I don't understand step 8.
Step 9: 'If we have lots of units, and they are not in a city or node, then maybe we have enough to just go attack something.'
Step 8: 'If we have lots of units, and they are in a node or city (perhaps... in a node literally adjacent to an enemy city), then we must go collect up with the rest of the units to build our doomstack.'
Why does being in a node or city matter? And if it matters, why are they NOT allowed to be aggressive and attack things, but they ARE allowed to leave their defensive position?
Posts: 10,492
Threads: 395
Joined: Aug 2015
So if I get this right, you want the stack that is already heading towards a target to override that order and turn back to fetch more units if they are within 8 tiles? And repeat doing this until the stack is full (9 units) and no "superior" unit is in a range of 8 to replace it?
Doing this can potentially delay the attack by a dozen turns, but fortunately intercontinental attacks don't "reserve" the target so it can still be attacked by others meanwhile. However if the stack is built over a land tile and the target is on that continent, land attack is going to be made, which does reserve a target so nothing else can attack it unless they quality for being a secondary attacker which is unlikely.
Aside from this the other problems I see are :
-Much slower for the AI. If the doomstack spends 6 turns heading towards its target, those 6 turns are not being used for anything at all instead of starting to assemble the next doomstack. This will decrease performance vastly on building "nondoom" doomstacks that are made from normal units such as pegasai. While this might not seem important, this is what makes the whole thing work effectively - there is a constant supply of good stacks. It's much less likely for the game to reach a stage where the AI has 9 very rare creatures then where they have 50 pegasai.
-"'if the current stack already has an order, such as attack"
This part is hard to implement. It would require checking every single unit's location and target coordinates, which is not a trivial amount of code. (X, Y, Target X, Target Y all have to be the same on all units)
-What if the strongest stack is not the doomstack? A stack can easily have the highest strategic strength while the units in it are not even in the top 30 the AI has. For example if the AI has 9 buffed lizardmen javelineers and 20 doom bats, the doomstack will be the bats, but the strongest stack would be the javelineers (assuming enough buffs). So step 1 has no effect in these cases - the units don't stay on the list and we are back to the original algorithm.
-The "strongest stack" changes too often and would be inconsistent.
-Finding an entirely intercontinental stack is slow (runs in x^2 time where x is the amount of units), I prefer to avoid that whenever possible.
-It doesn't really do anything about pulling the units it's not supposed to pull from nodes and cities - the only thing it does is slows down building stacks so it's less likely to happen - but it might still move out the 9 dragon turtles/pegasai/nightmares/etc all together from the AI's only city having those creatures if the previous doomstack was lost and those are the best units.
I see what you want to do with this but I don't think it'll work and it doesn't fix the problem, it fixes something else I consider a feature not a problem (building secondary stacks in the "background")
June 3rd, 2017, 07:21
(This post was last modified: June 3rd, 2017, 07:31 by Nelphine.)
Posts: 5,010
Threads: 17
Joined: Aug 2016
I've re-edited my posts.
I disagree about choosing doom bats over buffed javelineers. In many cases the javelineers are simply better.
The main purpose of what I want is to only ever have 11 units involved in doomstack building. The secondary stacks do far more for pulling from garrisons than the primary does.
Your concern about turning back uses exactly the same formula your own algorithm uses, so you would encounter it just as often. (I literally copy pasted it, and removed explanatory text, and added the part connecting the units not in the stack that are too far away.)
I don't think stacks switch strategic strength order nearly that often. Possible they do of course, but why would they? Buffing things does the most for strategic strength; buffing already targets the strongest strategic stack. (This is also why I'm confused as to why you wouldn't want to use this - you already use this targetting algorithm for unit buffs, why is it worse for this?)
Posts: 10,492
Threads: 395
Joined: Aug 2015
Quote:Your concern about turning back uses exactly the same formula your own algorithm uses, so you would encounter it just as often.
Nope. In my algorithm, a stack heading towards the target is not included in the list so it'll never turn back. (unless the target disappears or the stack is no longer strong enough to attack it)
Quote:Possible they do of course, but why would they?
Levels. Let's say you have a doomstack with 9 javelineers, each at 40 EXP and 9 other javelineers each at 21,22,23,24...29 EXP.
Next turn, the EXP 29 javelineer will be the same level as the doomstack. If it's older than them (for example was produced without a barracks while the others were with one), it'll be now on the top of the list and try to replace the first unit. Next turn the 28 EXP unit does the same etc. By the time this is all done, the AI builds a War College. The new javelineers made there are 1 level higher, so again every unit will be replaced one at a time while they are being made.
And that's not taking into account that the AI might randomly put Flame Blade on a javelineer elsewhere. Possibly the one that just got thrown out of the stack.
Quote:buffing already targets the strongest strategic stack.
It does not. It's merely one of the things that add to the priority of the target, but other things (compatibility with the spell, the strength of the unit itself, being or not being a hero/fantastic/normal unit, etc) matter.
Also the strongest strategic stack is NOT always the doomstack. Aside from what already mentioned, there are also land units that don't participate in the doomstack but are plenty strong, such as Behemoths or Colossus.
Posts: 10,492
Threads: 395
Joined: Aug 2015
Quote:I don't understand step 8.
Step 9: 'If we have lots of units, and they are not in a city or node, then maybe we have enough to just go attack something.'
Step 8: 'If we have lots of units, and they are in a node or city (perhaps... in a node literally adjacent to an enemy city), then we must go collect up with the rest of the units to build our doomstack.'
Why does being in a node or city matter? And if it matters, why are they NOT allowed to be aggressive and attack things, but they ARE allowed to leave their defensive position?
A garrison stack cannot attack. The attack procedure skips it.
But it can leave the location and then attack next turn.
If this step wasn't there, the doomstack would stay on the node/city, and the only way to recover it would be through land stackbuilding, which splits it up and pulls units one at a time.
Posts: 5,010
Threads: 17
Joined: Aug 2016
@turning back: Oh, I understand. Ok I'll add in that once its sent to attack, it won't turn back. (I realize it's not that simple, since I still want to use it as the doomstack but I think it's still doable.)
@levels: Doesn't matter if they're older. All the units in the strongest stack automatically get used. So even if a new unit becomes as strong (or even stronger) than the units in the strongest stack, all they can do is either join the doomstack, or chase it and become reinforcements. The only time it would matter is if the stack strength becomes a different order, in which case an entirely different stack would get used as the basis; the old stack (which presumably would still be fairly darn strong) might lose a few units trying to reinforce the new stack, but would remain largely intact to be used for standard stack building or garrisons.
@other stacks being stronger: Doesn't matter unless the entire stack is intercontinental. So even if you buff something that has land units in it and has stronger strategic strength, the worst that happens is .. nothing. Buffing doesn't change unit cost so it doesn't get tagged as reinforcements, and since the land units prevent it from being a doom stack, the stack doesn't get chosen.
@step 8: ... that's really aggravating. Makes sense, but I'd rather insert a special attack line into step 8, rather than simply move the units out of the node, fail to attack, and lose the node.
Posts: 5,010
Threads: 17
Joined: Aug 2016
Editted to account for turning back and for garrisons not attacking. (I'm assuming you can call the attack procedure directly from in here, instead of having to wait for the other calculate attack procedures. If not, and the ONLY thing you can do is abort, then this doesn't work.)
Posts: 10,492
Threads: 395
Joined: Aug 2015
Quote:Doesn't matter if they're older. All the units in the strongest stack automatically get used. So even if a new unit becomes as strong (or even stronger) than the units in the strongest stack, all they can do is either join the doomstack, or chase it and become reinforcements.
You mean those units added in step 1 ignore the sorting order while those in step 2 don't?
But then they'll never get replaced with a stronger unit even if one is available - that defeats the purpose of the whole thing.
Quote: The only time it would matter is if the stack strength becomes a different order, in which case an entirely different stack would get used as the basis;
What if they oscillate? Like, one turn a unit gains a level in one stack, putting it ahead. Before additional units reach it, the other stack gains a level (or is buffed) and is strongest again. And this keeps happening while the units go back and forth never reaching either stack. (Yes, I know it's not realistic to keep happening but even if it happens 2-3 times that's an entire year wasted. And there is no theoretical upper limit.)
Quote: rather than simply move the units out of the node, fail to attack, and lose the node.
That can only happen if the person stealing it is not an enemy.
Quote:I'm assuming you can call the attack procedure directly from in here
Absolutely not. This is the very last step in the overland movement process. Calling something that comes in the middle at the end again will override a lot of unit orders in a way that should not happen.
There are two attack procedures.
Continental attack, and intercontinental attack. Both use "stack data" as the input, built by another procedure for one continent only (which can be the ocean). The doomstack procedure works with raw unit data - it has no stack data built for any specific continent because it doesn't even work with stacks - it works with individual units. In theory it's possible to first build up stack data for the continent where the stack is on, search for the stack matching the coordinates in the data, and then call the intercontinental attack procedure with that but...that's so overcomplicated I'm not going to do it.
Btw even if this is done, the stack will not head to the main action continent if it fails to attack something in the valid range (as that is a different procedure, one that processes every stack at once, we can't use it here), so it'll stay on the AI's home continent, guardian a node even if there is an enemy wizard on a distant continent.
Posts: 5,010
Threads: 17
Joined: Aug 2016
Right. I think in that case, you can't build doomstacks - and you shouldn't try. Doomstacks are inherently quite different from a standard offensive stack. Doomstacks need to keep moving. (Which is why you don't replace them with stronger units, you simply reinforce them with the strongest units when a current unit is lost; it's also why you have 11 units assigned to the stack, not 9.) Doomstacks also need to be able to attack regardless of defensive requirements - which means, if you can make multiple of them, then you completely wreck your defensive requirements, as you've seen.
I think you should change your doomstack creation - make it 'faster offensive stack creation', and don't have it completely override normal garrison requirements.
So originally you had:
Defend fortress
Defend cities
Defend nodes
Build offensive stacks with whatever is left.
A proper doomstack would go:
Defend 2/3 of fortress*
Build doomstack
Defend 1/3 of fortress*
Defend cities
Defend nodes
Build other offensive stacks.
But, given the restrictions you've shown, you can't do that, and keep any momentum, without giving up too much of defensive requirements.
So I think you should change it to
Defend Fortress
Defend 1/2 cities*
Defend 1/2 nodes*
Build faster offensive stacks
Defend 1/2 cities*
Defend 1/2 nodes
Build standard offensive stacks with whatever is left
*Note, what I mean by these fractions is: Take your original defensive requirements; cut them to the first listed fraction (say, 1/2 cities) - so you'd only require to have half as many units as original defensive requirements. (If you needed 2 of the strongest summon; you'd now only need 1. If you needed 8 units total; you'd now only need 4.)
Then you'd build the doomstack/offensive stack; then you'd reach the second fraction, and you'd finish building up your defenses. (Add 4 more units including a 2nd of the strongest summon.)
|