Improving Ship Movement AI

Ship movement AI is the part of the game that I think needs the most work. Honestly all other considerations of balance are far less important because these variables will once again be shifted out of balance as the movement ai develops. What I feel will make or break this game, in terms of commercial success is the ability for the player to make their ships behave in a manner they envisioned when they put together the design. As a game programming student who has studied AI extensively I not only know how difficult AI programming is, but also the cost to you as an independent developer to focus your time on it. Thankfully you have a good solid community here who’ve already bought into (and purchased) the game and want to help you make it better.

I really think that GSB is a good candidate for use of steering behaviors for ship movement. 2d implementation of these behaviors is fairly simple, each behavior generates a steering force vector. The nice thing about this is it allows you to create complex behaviors by prioritized blending. Perhaps the most famous use of these behaviors is Craig Ventner’s BOIDS which combines separation, alignment, and cohesion to produce emergent flocking behavior.

The steering behaviors are
seek, returns a vector directly toward a target.
flee, returns a vector directly away from a target
arrive, returns a vector that allows the ship to glide gently to a stop at the desired location
pursuit, returns a vector toward a target’s predicted position (looks very smart, instead of trying to go where the ship is, trying to go where it’s going)
avoid, returns a vector away from a target’s predicted position (wouldn’t this be nice for a missile sniper frigate?)
wander, returns a vector with a controlled amount of randomness
obstacle avoidance, returns a vector to navigate around fixed obstacles ( like asteroids!!)
wall avoidance, returns a vector to keep away from the wall
interpose, returns a vector to place yourself between one target and another (great for tanking ships)
hide, returns a vector to place a target between you and an enemy ( great for artillery ships)
path following, returns vectors to follow created paths.
offset pursuit, returns a vector to pursue to set distance and angle from a target’s position (this will fix your formation problems and make dogfights cooler.)
seperation, returns a vector to keep a minimum distance from others
alignment, returns a vector to keep a similar direction to others in the group
cohesion, returns a vector to stay within a certain distance from the group

I think it’s easy to see how these could be combined to create great behaviors for each ship. For instance, I think groups of fighters should automatically flock together (separation, alignment and cohesion) but set the priorities low so they will break and attack when other fighters come around. And I want them to hunt other fighters, so I tell them to use pursuit to try and chase them down and get into firing range and put that at a high priority. (or better yet, an offset pursuit that tries to keep them behind the fighter and in optimal weapons range) Bombers could be told to avoid enemy frigates and fighters, and pursue cruisers while wandering to avoid AA fire.

The nice thing is these behaviors can be added into your existing framework without too much additional work. The current deployment screen setup would be compatible with setting these atomic orders and you are already using sliders for priorities in your attack order setup. There is the consideration that it might be overly complicated. A better method would be to create selection of effective orders that exist by default and then allow the user to learn how to create their own orders in a similar manner to constructing ships.

I think there are few really good advantages to this approach for GSB. It would work with the existing game, your ships are already calling some method to determine their desired heading each timestep, this would simply replace that method. You wouldn’t have to change your existing movement model to make it work. It’s very easy to implement in 2d and what the steering behaviors do is easy for the average player to understand. The tricky part is tweaking the variables for each behavior to get the results you want, which is exactly the kind of gameplay I think GSB players are looking for.

I learned about these steering behaviors from a book called “Programming Game AI by Example” by Mat Buckland. It’s easily the best book on creating functional game AI in my extensive collection. It also includes example implementation for all these behaviors.

I do like the idea of a new order for fighters squadrons which could be ‘stick together’ where they could do some basic flocking stuff, or at least weight that in together with the other desires to move in a certain direction. Either that, or they could all move within a certain distance of the nominated squad leader.

totally impractical - but what i’d like is for the AI code itself to be modifyable - obviously it’d need to be chopped-down and pre-battle compiled (no complex scripting language here).
even more so if you could expose variables for new code to the UI - so one could download an AI mod … and it’d show up as a new order, with a slider (optionally)

and i’d like a pony please :slight_smile:

Basic flocking would be awesome. The only concern I’d raise is the interaction between that and possible AOE weapons. Though I suppose flocking would reduce the initial stacking that fighters usually engage in, which would be horribly vulnerable to AOE anyway.

For fighters, I’d like to have an option for torpedoes especially where they zoom in, launch, and zoom out of range of AA fire, circle back, do it again. with torpedoes long reload time, it is more practical then them just flying around getting shot to pieces.

I’m curious why you think this is an impractical solution. The behavior implementations are actually very simple and they provide the pieces to build interesting behaviors. Even if cliffski never exposed the ai development to the community, there are methods in these behaviors that could be used on their own to fix some of the current problems with the game. For instance, changing the way formations operate to be a combination of offset pursuit and alignment would make for formations that did a good job of staying together and in position.

The Offset pursuit method takes 2 arguments, a pointer to the leader and a vector representing the offset defined in the leader’s local space. It then translates that offset position into world space and then predicts where that offset position will be based on the leader’s heading and speed and then returns a call to the arrive behavior for the predicted offset position. Literally 5 lines of code.

In laymans terms it figures out where it’s movement target for it’s position in formation will be based on a prediction of the leader’s current trajectory. This would completely fix the “lag” that happens when the leader ships start moving and the other ships can’t keep up. It would even take into account the the directional changes of the leader so that the formation rotates when the leader turns. And it wouldn’t require any changes to the player interface at all since the only things required for this behavior is to determine a leader and the offset position, both of which are done with the current formation setup in deployment anyway.

You can actually see a pretty good example of these behaviors in action if go to this website and download the example binaries (you can get all the example source code there too!!) They are all in the chapter three folder, there’s a bunch of mini programs that each demonstrate single behaviors with inputs for you to play with the variables.

Hardly. BOIDS ussed to run very well on pissy old PCs back in 1996.

If you leave out line-of-sight calculations, summing vectors (desire for target+direction, fear of threat+direction, desire for navigation way-point, etc) to find the current ‘proper’ course is just matrix sums. You can also modify weightings for ‘keep moving’ and ‘punch through then cricle’ and ‘flank left’ and so on. e.g. if you want to ‘flank left’ add in a vector that points to the screen-north of the centre of mass of every enemy unit, weighted for size.

Be nice to have some subsumption in there too, so you can say
e.g. for my fast fighters
75% attack enemy fighters
50% fear enemy cruisers
50% fear enemy frigates
– that’ll let them attack any free-roaming fighters but avoid getting drawn into the middle of enemy formations
2. subsumes 1
66% escort friendly frigates attacked by enemy fighters
33% escort friendly cruisers attacked by enemy fighters
– that’ll let them fall back to help the main fleet
3. subsumes 2
100% escort cruiser until attacked by enemy fighters
– they’ll wait for the enemy fighters to attack

so that the fighter squadron should wait till ‘their’ cruiser/carrier is attacked, deal with those enemy fighters, then go and find any more enemy fighters that are roaming around, but come back to help if any more turn up.

The ‘wait’ could be a flag field per unit type and per onboard equipment, and ‘attacked’ is already implemented.

Could also do
100% stay 700 away from enemy
2. subsumes 1
100% attack enemy frigate or cruiser if torpedo is loaded

so basically run away, dive bomb, run away, dive bomb, etc.

you’re all missing the point. the AI code is totally practical.

what’s impractical is writing/subverting a language to control it, implementing a parser/compiler, rewriting the current AI system to be data-driver, and letting players use it. the impracticality was in terms of development time vs payoff.

Also don’t underestimate the problems of scaling. A single flock of objects is fine, a battle with 30 fighter squads of 16 fighters each flocking is slower, especially given most of the CPU is being used for other stuff.

It is a major factor and does require some consideration and planning. Individual AI decisions can be accomplished very quickly but unchecked the complexity approximates O=N². There are quite a few ways to reduce this, the most useful one is a sensory model that prioritizes based on grid distance would limit the number of calculations per time step is an important start. Fighters easily become the biggest source of slowdown with their massive numbers, but there are ways to mitigate this as well. Having larger ships consider squads of fighters as a single unit who’s position is based on the approximated center of their formation instead of each individual fighter for purposes of movement calculations saves a ton of calculations per ship and greatly reduce effective complexity. Fighter squads could also computer their major movement decisions as a group, with the steering force vector result then passed to each fighter which then only make individual flocking decisions would also reduce your complexity level by a great amount.

I dunno, flocking behavior might make the game look more “2d”. I mean, it is 2d, but with the current fighter AI looking down on it is like looking at a 2d view of a 3d “Tie fighter vs. X-wing” battle with dueling fighters all over the place.

I like the idea of improving ship movement though. Currently, my ships always seem to fly into combat and then stay there until they die. I tried making faster ships, but this just means they die sooner (except fighters, which do much better when fast). Here’s my humble and unasked for suggestions:

Fighter movement: I love it the way it is. It makes it look like a real furball out there.

Cruiser movement: Cruisers are so slow it doesn’t seem worth it to change the AI much, but it would be nice if the cruisers would start turning toward the next target BEFORE the current one is completely obliterated. The weapons are on turrets, the cruiser could keep pounding target A without actually being pointed at A. The cruiser captains look stupid when they all point north to finish off a lone cruiser when all the enemies are to the south.

Frigate movement: Compete rewrite! (kidding) I try giving the keep moving order to my frigates but then they move about randomly, more like a “drink beer” order. What I want them to do is steer away from the unhealthy attention of big ugly cruisers. For instance, I deploy 5 frigates which engage one cruiser. The cruiser picks an unlucky frigate to try to kill. That frigate should move out of the way! Of course, frigate turn rates are so horribly slow that even if it tried to do this it would probably fail. I think frigates should turn faster and be more nimble in getting away from those big proton cannons. My meta-point here is that I don’t ever make my frigates go faster than my slowest cruiser. I would like to have a good reason to make fast frigates.