The AI thread.


#1

This is that thread. Let the nightmares commence!

I have a fairly good grasp of the order set, although there are gaps in that understanding or I of course may be incorrect. Perhaps you can fill those gaps in for us, Cliffski.

So we’re we’re all on the same page, I’m going to try to draw out the orders below.

There are two distinct unit behaviors currently in operation: Driving (pathfinding) and Gunnery (shooting). An order can effect one or both.

Gunners, by default, appear to have some sort of targeting table that they evaluate periodically. Targets that fire is ineffective against (extremely fast moving, penetration immune) go down in priority; many of the orders of the set influence this priority in some way. The gunners seem to have some understanding of tracking mechanics and will tend to prioritize large and/or slow targets if given the choice. For missiles, painted targets take priority over unpainted ones, but only if the ship has orders to attack the painted ship class. Ships without weapons (or modules not considered weapons) receive a lower priority than ones with.

Drivers operate off a fairly rigid set. At the start of the map, they either select a target, or hold “formation” as ordered. They hold this target until:
(if in formation) The formation lead dies
The existing target dies
Retreat to the map edge by a ‘cautious’ order

Attack X orders have two sliders. A percentage, and a distance.

The percentage has direct influence on gunner target selection across hull classes, and define the willingness of gunners to attack suboptimal targets. 50%-50% attack cruisers-frigates will have gunners prioritizing cruisers, simply because cruisers are generally larger and slower than frigates. 50%-70% will have the gunners attacking frigates more often, although they may switch to a particularly juicy 256m stationary target cruiser.

The distance slider only influences the driver. The distance is the range at which the driver will stop approaching the target. At exactly half this distance, the driver will attempt to move away from the target. As a result, drivers maintain a ring-shaped band around their target. The percentage has an unknown influence on the target selection, possibly in relation to distance.

Gunners without Attack X orders (like a cruiser with no “attack fighters”) will fire on those targets only while idle. The driver will not select these units until all other hull classes are destroyed.

Co-operative orders appear to influence gunners only. Gunners will increase priority on targets being shot at by other gunners in a sort of “peer pressure” effect. This is used to focus fire, although it can mean more fire than normal expended at undesirable targets (too fast, armored, shielded, unarmed). Note that a gunner with cooperative orders can cooperate with guns without that order.

Vulture works like cooperative in that it adds target priority to vessels. In this case, low health percentages add priority. Note that shields/armor are not considered, only health. Beam weapons may be attracted to fire at a low health vessel that still has a reflective shield up, for example.

Cautious is a driver only order. At a certain health percentage (again, not shields/armor) drivers drop target and head to their starting edge of the map. Fighters will return to the closest valid carrier, if possible. The driver will remain here unless the craft health goes back over the percentage value, at which point it selects a new enemy target.

Rescuer orders work like cooperative and vulture, adding priority value this time to firing ships, often rapidly switching priority between them. This is useful for engaging (or spraying) a number of units at once; EMP, antishield and antifighter vessels make particularly good use of this, as they often don’t want overlapping or wasteful fire.

Protector works like rescuer, but only for weapons fired on a particular ship. I don’t use it, considering the scale of large battles - does it even have a hotkey?

Escort is an additional constraint on the driver. If too far from the escort target (as defined by the distance) the driver attempts to move towards the escort target. Note that the driver will not attempt to do so if within Attack X range of it’s attack target - it will instead remain stationary. It’s possible to leave long range escorts “behind” if they decide to stop and engage targets. Fighters do not stop their movement patterns when using this order.

Formation defines a coordinate in space in relation to a defined vessel for the driver to move to. The orientation of the target vessel has no bearing on this coordinate, only the X and Y position. Due to acceleration factors, drivers tend to ‘lag behind’ the defined coordinate.

Retaliate works like rescuer, but for ships firing on that vessel.

Keep Moving is a unique driver-only order that initiates a drunken movement pattern when the driver is idle - this occurs within the range band around an attack target. It is incompatible with escort and formation.

Stick together is a driver-only order for fighters that makes them hold a formation. The fighters follow a lead target rather than individually determining paths; this target should always be a healthy fighter on the attack. Fighters that peel away via cautious commands do not seem to return to the formation.

No attack: Units without any attack orders exhibit some strange behaviors. Drivers will repeatedly switch targets on the fly based on proximity, gunners and drivers operate off a set of internal range/percentage values that aren’t fully known to us.


#2

Some obvious or common requests:

Keep moving is incompatible with escort, even though fighters appear to be able to do this at all times.

Cautious orders do not take shields or armor into account. Being able to retreat armored fighters before they take engine damage or frigates before they lose their shield is desirable. It would also be nice to be able to use this order without the risk of getting units stuck on the edge of the map if they can’t reestablish their conditions.

Formation orders leave many players unhappy. Taking target ship orientation into account is an important first step.

There are quite a few situations where the current AI can do contradictory or detrimental things. I’ll try to give some examples:

Laser/pulse fighters:
These fighters move quickly and have very small range windows to operate in; they are a prime example of gunners not working with drivers.

A set of fighters attacking a cruiser make repeated passes through the cruiser’s shield bubble to deliver damage. The shots will go through a pattern of immune-damaging-immune, as the fighters can’t damage the cruiser from outside the bubble. Against a single cruiser in the open this is fine; but against a cluster of targets this can become a problem. The gunners can rapidly start flopping priority between cruisers - posters other than myself have observed them switching firing targets right before passing through the appropriate shield.

Sometimes vulture or cooperative can clear this up, but during all of this the driver is patterning after the same selected target. It’s possible for this target to drift further away from the other cruisers, leaving the fighters unproductively focus firing on damaged cruisers from outside their bubble. Drivers can also seize on fighter targets and take the gunner for an absolute ride - I’ve observed fighters chasing rocket fighters while haphazardly spraying cruisers they pass over.

Exacerbating this are the multiple types of ‘immunity’ from fighter lasers that exist. Fast rocket fighters can’t be hit at greater than 2% chance, cruisers can be armored to the point where only 2% of fire is effective, small frigate shield bubbles increase the time fighters spend firing uselessly. A fighter driver permanently seizing on any of these targets can prove disastrous for the entire squad.

On a related note, gunners can take nontrivial amounts of time to reestablish a new target after the old one goes out of range. It’s not uncommon to see individual fighters stop firing one or both weapons for extended periods during fighter battles.

For fighters more than any other class of unit, there needs to be some relationship between driver and gunner. Fighter gunners also need to be more keenly aware of the target that is closest - shield bubbles are a unique positional problem for this class of ship and there’s really no other way to get around that.

The dreaded Armor block:
On level start, drivers usually select the closest target. A common tactic for challenge fleets is to throw a few ships of obscene armor class in front for drivers to seize on. As a result, these enemy ships becomes a deadweight anchor for your entire fleet; fighters, frigates, and short range order cruisers all clump up uselessly on these blocks while long range units stop and hammer on these targets while never getting in range of the softer ones. If the challenging player is feeling particularly cruel, the anchor ships can be given movement orders to lead your fleet around into more disadvantageous locations, or simply to hold your fleet in place while it is approached.

This infuriating behavior can be prolonged by leaving the armor blocks unarmed; the gunners with non-immune targets will (appropriately) fire on those, splitting the fleet fire up further. Scramblers, point defense, and tractors are apparently not considered weapons by gunners and thus do not receive priority; these defensive measures can be employed on ‘unarmed’ ships (armored or not) to foil various kinds of attacks for very long periods.

This is similar to the fighter problem, although likely more complicated to solve. Cruisers and frigates can have a wide array of penetrating values; choosing when it’s appropriate to start ignoring a target may be difficult.

Questions about defensive effectiveness are raised by this. The employment of armor usually reaches one extreme of being useless or unfair; it’s countered too easily at low values and is far too harsh a counter when penetration doesn’t happen. A happy medium may make this defense less problematic; possibly a degradation of block percentage from damage instead of the penetration threshold.

Lack of avoidance:
I bring this up a lot, but I feel it’s very relevant. The most infuriating thing in the entire game is watching a fast ship with long range lose to a slow one with short range. What is important for even a basic avoidance model is that drivers have some kind of awareness of the closest enemy ship of each class, and that some condition for a target swap is allowed.


#3

Agree with most things except this part.

For a challenge maker, high armor has limited use and is not nearly as effective as you made it sound here.

Armor blocks move at 0.6 speed at best, you can’t “lead” a fleet anywhere, nor could they survive that long.
Because armor block moves at 0.6 speed, the rest of your fleet also must move at 0.6 speed. Because of this, in long range long range wars, armor blocks will get hit a significant amount before attack ships gets in range.
They get easily killed by beam lasers even with armor > 70.
Armor blocks cost large sums of credits. If the person armor “wall”, it cost so much credits that you can easily kill the back row with your own long range and the rescuer tag.

Besides, it’s not like Order or Nomad are currently overpowered because of armor blocks, so why nerf them?

Decoy brings dynamic to the game, take it out and you are left with (Tribe) spams and counter spams.


#4

Demonstration fleets in the past have shown otherwise.

Look, this thread is about the AI. It’s not necessary to use armor or even to use long range ships, this is just the typical way the tactic is seen.

Let me just copy a section from Guide: Positioning and Movement, because he illustrates the problem much better:

The fact that the longrange ships happily go rushing to their doom is pretty horrifying. You only need one ship to do this with - a level of armor is only necessary to prevent faster elements (fighters, frigates) from assassinating the anchor unit.

If we want to enable mobile tactical endeavors, the driving AI has to be improved in this area. Used intentionally or not, this is really frustrating behavior.


#5

Personally I don’t see this particular AI pattern as such a bad thing, since decoy seem the be the only tactic available that influence enemy ship behaviors.

To name a few more, there are the “split the army in 2” decoy (corner deploy 1 fleet with 1 decoy on opposite corner), the anti fighter decoy, the frontal armor wall, the ratio raiser in the back corner (to force a fighter vs fighter), the weaponless fighter lure, and the formation breaker.

Or perhaps I am not understanding what you mean by mobile tactical endeavors. All I can foresee without decoy is spams.


#6

Ok, there are so many things. But I’ll just talk about one order for now.

Attack X

There are 2 parts.

Priority: (values should mean this)
1% ignore this class for pilot target until it is the only class left (be nice to have a zero on the scale)
100% attack this class to the exclusion of all other classes (be nice to have an ∞ (infinity) on the scale)

I actually think there’s some better controls for this but I need to collect my thoughts.

Move to attack at this range:
Works just like it does now, with one exception, when “Keep Moving” is on. The ship should “orbit” the target trying to keep it’s range at exactly the specified range. For a visual understanding of this, it should look like an AC1000 does when it’s fireing its big guns (from Sup Com 2).

You need to be able to set the range on ignored classes so that when it’s the only class left you engage it at an optimal range.


#7

Another order.

Fighters should not need cautious orders to repair themselves if there is a carrier present. Perhaps the loss of a module would trigger the retreat.

As it is right now fighters with no guns do not repair themselves when a hanger bay is present.


#8

Fighters should not need cautious orders to repair themselves if there is a carrier with supplies present.

I’m not sure about the “loss of a module” thing, because that’s likely to be the engine. However, I suppose this would be especially reasonable if it applied to armor… i.e., the loss of an armor module (due to extensive armor damage) triggers the “go back for repairs” behavior.


#9

Good point.
Engine under 50%: run for repairs!
Any other module gone (armor, gun, powerplant, etc): run for repairs.

And yes the fighter should radio the carrier to see if supplies are present, no sense docking to find out there are no supplies.


#10

Cautious Order:

Previous conversation was a great segway to the Caution Order. It should have three parts.

Shields (in percent from 99 to 0):
At 80%, if my shield drop below 80% I run for the back wall. If my shields recharge (100%) I break out of Cautious return to battle. If I’ve lost a shield module the resulting shield strength is 100% for calculation purposes. Meaning if you recharge to 100% of what you can produce you break out of Cautious and return to battle. If my shields drop below the percent and then collapse (no shields) I return to battle (no shields this part of Cautious is ignored).
Armor (in percent from 99 to 0):
If I drop below the percent, I run for the back wall. If I am repaired above that percent, I return to battle.
Hull (in percent from 99 to 0):
If I drop below the percent, I run for the back wall. If I am repaired above that percent, I return to battle.

In all cases if I touch the back wall I return to battle.

This IS designed to create a ping-pong effect, so that one cautious retreat does not mean your lose the ship forever.


#11

A possible problem with this order is that it controls both driver and gunner at once, where we in fact have differing intentions. I can make a frigate that I want shooting 90% of the time at fighters, but I don’t necessarily want to have it chasing after them if it breaks formation.

That’s due to the simplicity of the driving AI. It only does one thing.

If frigate drivers grew a proximity fear response to cruisers overnight, suddenly you can influence enemy formations with fast cruisers. You can do interesting things like push frigates away from your ranged units or chase them into corners. The other guy can happily churn out annoying plasma frigates that can dodge cruiser plasma or even missiles at full speed without worrying about them blundering immediately into CL range.

Without that AI response, none of those things will ever happen. We have to add complexity to get complexity.

Gunners are complex and there are lots of ways to influence them. I’m fairly happy with those, save for maybe three things:

  • Fighter/shield bubble interactions outlined in the second post
  • The problem of long cooldown weapons being fired at inappropriate targets (megaton or torpedoes fired at fighters, although these weapons also… suck.)
  • Scramblers, tractors, PD, and other possible modules not considered a “weapon”

Most other problems discussed arise from the driving behaviors of the platform.


#12

I don’t really have any arguments to add, but I’m sitting in the background rooting for yurch on his quest for “avoidance AI”.


#13

If I had time right now to address just one thing, should it be the formation order? Thats possibly quite easy. When you are talking abaout avoidance, I presume you are meaning to always stay X distance from Y. The problem with this, is it gets phenomenally involved. X distance in which direction? There is a danger that you end up flying towards enemy lines to get away from a specific enemy ship thats made it to your lines.

I also agree on the stupidity of fighters attacking shielded enemies. This is much harder to fix, but I shall take a look.


#14

“Avoidance” may be the wrong term. I don’t think it’s that we want to avoid a specific ship… it’s just that we want the ship to look at the closest available target, and continually re-check to see if there’s a more appropriate target.

For example, let’s say my ship targets a cruiser out in front, with no engines. My ship will go after that cruiser. But if the enemy has cruisers with engines, there will come a point where those cruisers become closer than the one I was chasing. It makes no sense to keep chasing that lone cruiser in the back when all these cruisers are coming up right in front of me. At some point, the ship should adjust its target to the nearest applicable cruiser, get within a certain distance according to its Attack Orders, and start firing… not continuing to chase the cruiser in the back, plowing through the entire front line.

“Avoidance” in this context means avoiding all nearby enemy ships, not a specific ship. If you have an Attack Frigates order set to a high priority and a distance of 800, for example, the current AI will try to maneuver the ship within 800 distance of your navigation target. The concept of “avoidance AI” is that the ship will instead try to maneuver within 800 distance of the nearest enemy frigate, whichever ship that might be, at any given time.

If you wanted your ship to be doggedly determined to go after a specific enemy target, regardless of any other nearby targets, that should really be its own order, rather than the default behavior.

So basically there’s two parts to this request:

  1. The ship should continually seek to target the closest applicable enemy target, and maneuver within the specified striking distance of that target.
  2. When maneuvering away from the target, it should choose a route that will send it the furthest distance from all nearby enemies.

They are both important, but I think the 1st is more important than the 2nd. In fact, the better the 1st part works, the more likely that a simple retreat back to your deployment zone will usually be the safest course.


#15

It sounds like a lot of these problems are simply a matter of ships not re-evaluating the decision to stick with their current target. Frankly, this sounds more like a bug than a design flaw, and one I’ll take a look at. I’m pretty sure that all ships should be re-evaluating the sense of their current target decision periodicalkly anyway, so I shall take a look.


#16

Thank you, cliffski.


#17

To complicate things, there’s two possible schools of thought on formation:

Formation relative to lead’s rotation
Formation relative to lead’s target

The first would mean a formation frigate always stayed “behind” its lead cruiser. The second would have that frigate staying on “the other side” of whatever the lead is attacking. You could make an argument for either.

That would be fine, actually. The most relevant thing to avoid is the closest - if an evading vessel moves too close towards a different enemy, then that one eventually will be closer. The unit will either pingpong it’s way out or get surrounded, either way that situation is miles better than what we have now.

We already have a fairly working ‘move away’ behavior in that units move away from their target at the halfway range. We just lack a way to define that avoidance distance (half of plasma range is virtually CL range, that’s way too late) and a way to jog drivers off their current targets.

I’d envision it as a new order, “Avoid Cruisers/Frigates/Fighters” and a distance. Drivers would switch targets to and move away from the closest class of craft within the given distance.


#18

Agree. Being able to set when to move away will come in a big help, so we don’t have to set our engagement range to 2x our firing range.

A new command “Retreat Range” with the range of 10% to 90% can help solve this. This can work simply by replacing the default 50%. It doesn’t have to be separate per say, and by using percent it avoids the “what if people set retreat range to be > engagement range” problem.


#19

I’m spending some time on this now. I suspect the not picking fresh targets thing is simply a checking interval being unusually long. It’s set to 2 seconds, but for techhy reasons I think it ends up being 5.
Anyway, here is some pseudocode for how some stuff works, FYI:

[code]SIM_TargetedModule::SelectOptimumTarget(bool bignoreclass)
{
if Current target is docked
Set target blank
for each enemy intact ship
if docked, ignore
if leftbattlefield, ignore
if ignoring that ship class, ignore
if range to target outside min and max, ignore
set targetscore to be 1.0
if sum total of HP of ships attacking our target is more than 10x strength of enemy target, reduce score by 0.25
if we have fired more than 3 ineffectual shots at this target, reduce score by 0.5
if target is a fighter, and its tractored or has limpets attached, add 1.0 to score
if we have co-op order, add 0.125 for each ship also targeting our target, up to a max bonus of 0.5
if we are a shield disruptor and enemy has no shields, ignore
if we have vulture order add score bonus of 1.0 - hull integrity, to a maximum of 0.5
if we have rescuer order, add a bonus, max 0.5 to ships that have fired recently (within 2 seconds)
if we have retaliate order, add 0.5 if they are attacking us
if we are a missile and target is painted, add 1.0
if we do NOT have vulture order, and target poses no threat, reduce score by 0.5
multiply remaining score by the target priority given to attacking this class

select the highest scoring target as this turrets new target
}
[/code]

If no target is found, the whole thing is re-run ignoring classes, so we at least find some sort of target. This is the code for individual turrets, not the code that determines where to fly to.
This is also pseudocode, the actual code is pages long :smiley: And its run for everfy turret on every ship, so I can’t be running it all the time. Some of the calculations take time. I think one thing that leaps out there as not being known to anyone is that the vulture order overrides the normal desire to ignore ships that have lost all their weapons. Handy to know I guess :smiley:

Let me know if this is any help or interest, and if you spot any possible conflicts there.

actually… any volunteers to test drive a change to the frequency of ships re-evaluating targets? Anyone who has decent test case deployments already set up and knows what to look for?


#20

One thing that just occured to me. It would be fairly easy to add code that basically says this…

If you are a fighter, and inside the shield bubble of an enemy ship. prioritise shooting that ship

That should be a simple and noticeable improvement methinks?