# Getting a Ranged AI “In Range” to shoot

In my game, ranged units and melee units have the same behavior. Ranged units try to maintain a fixed distance r, from their targets. If they're within r + d of the target (where d is a small value) they stop and shoot it. Note that this means the ranged unit can't be closer than r - d. Melee units are the equivalent of ranged units, but with r set to zero.

Right now, my AI for ranged units is as follows:

1. Find a path to the target using A*.
2. Walk along the path until you are within [r - d, r + d] of the target.
3. Stop and shoot. If the target is dead, quit.
4. If you are still within [r - d, r + d], goto 3.
5. Otherwise, move away/towards the target until you are within r + d again. Goto 4.

Here's a sort of diagram.

My problem is, if there are obstacles and the target moves, step 5 causes a lot of problems. Ranged units will end up backing into walls, unable to shoot. If instead of going to step 5 I go back to step 1 (planning a path), the problem still isn't solved, because walking toward the target will only decrease the range, not increase it.

How can I get ranged units to successfully follow and shoot their targets?

• When they hit a obstacle, why dont you just pick the closest free direction from the direction "away form target" which was following previously? You could also improve it with BFS look-ahead to make it see the wall sooner. Wouldnt that work? – wondra Mar 1 '15 at 23:36
• That sounds like a pretty good idea. I don't need to do a full plan, I just need to look ahead at the neighboring cells, and find the free one furthest away from the target, then move towards that. – mklingen Mar 2 '15 at 1:10

There is really nice article at Rogue Basin on Dijkstra Maps about the problem you are encountering. This kind of "exploit" can be easily overused, cornering range units, while they are try to flee, they really stuck and can't move away.

The article describes making "negative" Dijkstra maps. You create normal Dijkstra map, multiply result by value -1.2, and pass that value back through same function. You will get map with negative values which negative values showing most optimal range away from player. Basically you will have your A* map for approaching algorithm and negative Dijkstra map for flee.

My own implementation shows really nice AI routines, removing exploit noticed above. When enemy is cornered in small room, he will try to pass you trying to flee to space which have exit, and then again shoot at you.

• This is also an interesting solution. It reminds me of "value iteration" in robotics. Basically, you want to compute a policy for the agent that takes it away from enemies. I will have to think of a way to compute policies for the ranged AIs that aren't too expensive. – mklingen Mar 2 '15 at 17:51
• Yes, that's what I was suggesting in the last line of my answer, too. It's especially good when you have a large number of units who all have the same general criteria, because you only need to analyse the map once for all of them for this purpose. I would still say that it's best to have some exceptions for specific units that find themselves in some sort of trouble. – Dronz Mar 3 '15 at 17:26

First think of what you would do as a player (and/or ask others what they would do) and then try to program one or more of those strategies.

There are probably several situations where a simple rule won't be a good idea to follow. This is actually a good thing, because otherwise your game would be fairly pointless to play as a human. Having an AI that can respond to many situations in interesting and challenging ways that make sense often makes all the difference between an interesting fascinating game, and one that seems very predictable and artificial.

In this case, consider that it is interesting and good for a melee unit to be able to out-maneuver a ranged unit in this way, pinning it against an obstacle. The only question is what you want the ranged unit to do when that happens. It might be good if it has a random choice between possible approaches.

If it makes sense in your game world, you might have the ranged unit detect when it would move to a wall, and if so, prepare a melee weapon and fight as a melee unit at least until it was another option.

If it doesn't make sense, the ranged unit who is trapped could at least try to run away (a* variation to nearest place that is far enough away, or safest overall for current situation - perhaps by running towards nearest friendly melee units), or even surrender if really cornered and helpless.

For an RTS game with many units, it may make sense to keep a pathfinding map for each side which rates each part of the map for how good it is for your ranged or melee units to be there, based for instance on where the enemy threats are. You can update that one map gradually (nowhere near every frame or it will take a lot of unneeded processing), and use it for tactical pathfinding like this. For example, for rating how good a spot is for ranged units, you can say it's bad if there are enemy melee units too close, unless there are some friendly melee units there too, but it's good if there are enemy targets somewhat nearby, and it's a little bad if there is too much terrain nearby that limits fire or movement.

• I guess this is the right answer. To clarify, the game is an RTS, so there isn't a "player" per-se, only the player's units. Modifying the AI slightly so that it moves to the free tile furthest away from the target makes for more interesting behavior, but you're right that I should probably make them fight hand-to-hand when cornered. – mklingen Mar 2 '15 at 7:00
• One of the most common complaints about RTS games is AI that requires the player to intervene to save their units who are doing something useless unless the player gives them an order. I don't quite see why "furthest tile away" would be the best choice, but it's one option that could be mixed with others. I'll add an RTS suggestion above. – Dronz Mar 2 '15 at 16:15