Picture this – you’ve built up just about the toughest merc outfit this side of the sector. Your officers are all hardened veterans. Your ships are outfitted with the best weapons and hull mods. Your skill is legendary, your reputation for prevailing against incredible odds unrivaled. Then, you encounter a small enemy convoy – they pose no threat, but the resources they carry would be a welcome addition to your cargo holds. With hardly a second thought, you order an attack – but really, does such a minor fleet action demand your personal attention? “I’ll let my second-in-command handle it,” you decide as you press the button to auto-resolve the “battle” not worthy of the name – it’s target practice, really. But a nasty surprise awaits – you’ve lost a top-line ship, and two elite officers are dead!
… and that’s the scenario we all want to avoid. Auto-resolve has great potential to frustrate the player, because it can obliterate their progress (in the form of resources, ships, and officers) – but worse, it can do this unfairly. The unfairness comes from breaking the player’s expectations of how the game world works. In our example, the player knows their fleet can mop up that convoy – but auto-resolve plays by a different set of rules, one the player hasn’t been exposed to before, one that isn’t clear. Even worse, the rules are hard to learn because they’re hidden. In the situation above, the player might assume that luck plays a big role – but it may well be that the officer skills weren’t valued as much as they should be, or the weapons you’ve equipped the ships with, or any combination of those and other factors. The player might give up on auto-resolve entirely – there’s no clear way to get better at it, and it’s not apparent whether improvement is even possible – and the player is punished for experimenting.
It’s still necessary though, because the alternative is having to fight every piddling battle yourself. Besides, battles that don’t involve the player need to get worked out somehow. So how can we address these underlying problems? Because I like lists, let’s make a list of things that aren’t fair to do to the player:
- ignoring any improvements they’ve made to their fleet – be it weapons, hull mods, officers, character skills, anything at all that has a bearing on combat
- ignoring the overall rules of combat the player knows – carriers increasing the effectiveness of fighters, bombers being effective vs large ships, point-defense weapons countering fighters, etc
- destroying any ships which would absolutely never, ever get a dent put in them if the actual battle was played out. A wing of Talon-class interceptors should have no chance to take out a wing of Wasps, for example.
To sum it up, the auto-resolve system has to roughly simulate the way combat plays out, take all relevant ship & fleet stats into account, and be very careful that “adding a degree of randomness” doesn’t become “anything can happen”.
One thing we can’t take into account is the actual player’s skill at piloting (not their character’s skill, which can be). That’s ok – a battle where the outcome hinges on the player’s personal skill shouldn’t get auto-resolved to victory, anyway. More importantly, I think the player wouldn’t expect auto-resolve to do as well as they do with themselves at the helm.
In the remainder of this post, I’ll talk about the approach I decided on and give some examples of it in action.
A natural way to design the auto-resolver is to approach it like a turn-based game. A “simplified Heroes of Might and Magic battle simulator” is an apt comparison to how it turned out. If you haven’t played HoMM, it’s like King’s Bounty. If you haven’t played that either, it’s like the original King’s Bounty from the early 90s. If you haven’t played any of those, you’d probably enjoy them. For the HoMM series, I’d suggest the 3rd one… but I digress. Where was I? Oh, right – designing a turn based combat simulation based on the real-time combat of Starfarer. Yes.
The first step is to come up with the stats of our units, the ships. We have to do that with an eye towards accurately representing the real-time dynamics of the game in a turn-based environment, of course. The actual set of stats evolved as I kept fine-tuning the auto-resolver, but it didn’t get too far from the starting point. Here’s the final set of ship stats:
These reflect how tough a ship is to bring down – two sets of hitpoints, with damage getting through the shields causing the ship to be damaged after the battle. For simplicity, shields don’t regenerate during the battle, but the regeneration rate is included in computing the shield strength. Both stats also reflect how difficult a ship is to hit, with faster ships having increased hits/shields values.
Attack, Point Defense, Strike Attack
The goal of having these three is to reflect the most important counters present in real-time combat – PD vs fighters, and strike weapons (bombs & torpedoes) vs large ships. Notice that damage types are not reflected here – they could be, but it seems to work well without them. It’s an extra level of complexity, and would require a more detailed hits model – you couldn’t fold the ship’s maneuverability into its hitpoints anymore.
These are used to modify the hitpoint values, and also affect the chances of a ship to escape/retreat.
Number of Flight Decks
Each flight deck can double the hitpoints of up to two fighter wings in the fleet.
The computations to come up with these values get a bit involved – suffice it to say, it took a couple of days to design the overall system, and at least double that time to fine-tune the calculations until the battles worked out right. Everything from hull mods to mounted weapons to officer personalities and the commander’s skill is taken into account.
The second step is creating a system that mimics how battles work when played out in real time.
First up is a “skirmish phase”, to reflect the jostling for objectives that happens at the start of most battles. The relative strengths of fast ships in each fleet are compared to determine which side got the advantage. No damage is dealt in this phase. The skirmish advantage that can be gained is reduced when small fleets are involved – can’t exactly split the enemy forces if all they have is one ship!
In the second phase, the ships fight it out. A ship is picked at random to attack – but the outcome of the skirmish makes it more likely for a winning side’s ship to be picked.
Then a target ship is picked from the enemy fleet. If a ship has good strike weapons, it’s more likely to go after a large ship, while interceptors are more likely to target enemy fighters. Higher commander skill improves the odds of getting a beneficial target pick.
Then the damage dealt to the target is calculated – a combination of attack, point defense, and strike attack, with coefficients based on the target type. For example, strike attack deals a lot more damage against cruisers and capital ships, and no damage at all against fighters and frigates. The target also gets to fight back, but only once per “turn” – the ability to fight back is reset when a ship is picked to be an attacker.
This process is repeated until all ships on one side are disabled, destroyed, or have retreated. When the number of remaining ships becomes small, the amount of damage they deal is reduced to mitigate the effect of luck.
Sample Battle Results
A good way to test this system is to have it run some battles that we’re already familiar with – and what better than some of the current missions?
Here are the results – with the chance of the player’s side winning the battle. Each simulation was run 10,000 times – incidentally, taking around a second to do so. The performance isn’t so important for battles the player is involved in – even if it took a second, that’d still be acceptable – but battles happening on the other side of the sector should not cause any delay.
Fair warning – f you haven’t played the game, these aren’t going to make a lot of sense.
Turning the Tables: 75%
The very first mission. It’s an easy one, and 75% seems about right. It’s certainly possible to lose if the enemy bombers get a good strike in, or if the Lasher frigates fire off a well-timed missile salvo. Replacing the bombers with heavy fighters boosts the win percentage to 88 – they have a much harder time handling the heavier ships in the player’s fleet.
For the Greater Lud: 62%
A fairly easy mission. The enemy cruiser poses a big problem on paper, but the player’s fleet has a number of bomber wings to take it out. If it weren’t for those (if they’re replaced with heavy fighter wings), it’s not even close – the score drops to 33%.
Hornet’s Nest: 14%
A medium difficulty mission, with the player commanding a far outnumbered, high-tech fleet. It’s not too hard to do well in the early going, but eventually the enemy numbers start to wear you down. It’s obviously hard to say whether 14 percent is exactly right (whatever that even means), but it doesn’t seem unreasonable. After all, it takes a good amount of piloting skill to get a win. The enemy fleet only has a single small carrier – but removing it boosts the player win percentage all the way to 40, because of all the fighters in the enemy fleet.
Predator or Prey?: 0.1%
This one is tough. The player’s fleet is outgunned, outnumbered, and the enemy fleet is full of strike craft that counter the player’s flagship really well. It takes a decisive attack on the enemy carrier and a fair dose of luck to win. Replacing the enemy bombers with fighters raises the win percentage to 2.5, but it’s really the combination of a quality carrier with a swarm of fighters – whatever the type – that makes the opponent so hard to handle.
Having played those missions to death myself, I’m pretty happy with those results. If one thing is certain, though, it’s that we’ll keep tweaking and refining this system as development goes on and issues crop up. One thing I wouldn’t rule out is
cheating erring on the side of caution to benefit the player, should situations like the one outlined in the opening paragraph still arise from time to time.