Game Design, Programming and running a one-man games business…

Programming AI in a tower defense game

This is not an easy task. It is for most Tower Defense games, because they are simply scripted. The level has a set number of enemies of certain types and times, and they appear as attackers. And of course, most TD games don’t let you play as the attacker, so programming the defense AI is not needed. I need both of these to be non-scripted for Gratuitous Tank Battles.

I need attacking AI that ideally adapts mid battle to your decisions, and this is harder than it sounds. The first approach I took was to have a system with 3 types of placement timing mode (steady placement, or hoard points for a big attack or spam the current unit) and two types of unit selection (random, and select the one that has been most effective so far…with some variation).

The AI would switch randomly between these combinations and it looked pretty convincing. Sudden waves of identical units followed up by who-knows what. The problem was, it obviously did so with little care as to what it was up against.The ‘most effective unit’ code was good, because it meant totally useless designs which charged into a hail of bullets would not see much repeat business, but something major was lacking. That was the anticipating of future events.

If the defender has placed 6 machine-gun turrets (rubbish, but devastating to infantry) you shouldn’t place down infantry, regardless how well they did earlier in the battle. If they have lots of laser turrets, place down shielded units to get past them…etc.

So today, at the end of a long day of video rendering and editing, and tweaking, and bug fixing, I’m starting work on a more generic system for opponent army composition analysis, that can take snapshots of the enemy forces and realise that its 63.2% anti-shield units, and thus we should de-prioritise shielded unit selection etc.

This is annoying, fiddly, long winded code that nobody will ever see, as such, but will make Gratuitous Tank Battles a convincing challenge, which is well worth spending time on.

Debug Tools and defensive AI.

Life is so much simpler when you bunch up all your hotkeys and toggles for debugging the game into a single menu. I feel like I have a rough idea what’s going on now. I also feel more confident about coding decent defensive AI when you play as the attacker:

The code for defending basically needs to manage three things. The play style (Is it spamming units, hoarding points, or steadily placing), The choice of units (Does the enemy have units weak Vs lasers? Are there lots of infantry needing flamethrowerising?) And the choice of unit placement. I’ve been concentrating on the unit placement debug UI today, so I can see what the AI is thinking when it chooses to place a turret at X rather than Y. More work to do, but currently it evaluates proximity to enemies, their size, victory-point value, closeness to the exit and proximity to the placement, plus it also has bonuses for being able to cover multiple paths from a single location.

It all needs lots of tweaking and balancing obviously, but it’s getting there. Attacking AI is much simpler.

After getting this stuff done, I’m thinking of experimenting with a unit ‘cooldown timer’ beyond a certain level to prevent spamming the same unit everywhere. Essentially there are supply delays if you plonk down 4 heavy tanks all very quickly, as new ones need to be dispatched from your offscreen HQ. I think it might be a good mechanic that encourages variety.

Shadow maps make me happy

I’ve been watching some WW2 footage, some war movies, some video game footage, etc, in a bid to up the visuals in GTB. A lot of it can’t be seen in a screenshot, it’s moving-picture stuff really. UI’ve also been re-visiting how I make the shadow maps, and massively boosting their resolution. What PC’s can’t handle a 2048 square texture these days? None, I suspect.

Anyway here is a very sparse GTB screenshot:

And here is the same frame, but without the shadowmap.

I think the shadowmap wins by a huge margin. (It’s more apparent full screen, when moving and zooming etc. Combining a grayscale shadowmap with tileable textures not only makes it look less 2D, but it also means you can detect the repeating tile patterns a lot less. I am using a tile-based system to afford easy level design for players. I’m also toying with the idea of automatically generating the shadow maps from the player-designed paths. I think it’s quite doable, although non trivial, and better than expecting players to use photoshop etc.

Comments?

Anatomy of a gratuitous bug

I think I’ve fixed a bug in the gratuitous space battles campaign game. I’ll know ‘officially’ soon, but it fixed it on my machine :D Here’s what was involved.

A player complained of a random crash bug at the end of some campaign battles. I could not ever reproduce it, and back-and-forth emails began. Eventually, this awesome customer provided me with exact steps to reproduce, and all their save game data to let me replicate it. First run through and….. nothing. It was fine. Roughly every third run-through, in release mode it crashed…

Step 1! Hurrah! it actually crashes for me. This is 50% of the battle because then I *KNOW* that it is the games fault, and not the gamers system, or software. This is good, although frustrating news.

Step 2! It crashes in debug mode. This is another 25% of the battle because I can actually see what data is corrupt. As it turned out, the ‘firstfleet’ pointer in the code that assigns captured ships to the players winning fleet is clearly trashed. How did this happen?

Step 3… debugging. It transpires that the firstfleet pointer is accessed multiple times before this point, and after being initialised, confirming that it *must* have been valid, and becomes invalid between initialisation and access when adding captured ships to the fleet. This means we  can step through and watch what happens, if I break on initialisation..

Step 4 discovery! Stepping through the code confirms my suspicions. Once the battle ends, the code updates all the players fleets and removes ships that died in battle. Then, other code innocently picks the first of the players fleets in the battle, and initialises a dialog box listing the enemy captured ships that will be assigned to the fleet. Later…. *drum roll* it deletes any fleets that are now empty. Can you see the bug yet?

Step 5: fix! Changing the code that naievely picked the ‘first fleet’ to pick the first player fleet that still has some intact ships ensures that the later deletion of an empty fleet, and invalidation of the pointer is harmless, because the captured ships are now getting added to a surviving fleet. Bug probably fixed, pending the player confirming that a new exe fixes it.

Why did I not spot this bug six months ago? Well here is what has to happen.

  1. The player has to fight a battle with multiple fleets at once (common).
  2. He has to win (fairly common)
  3. The ai has to lose by the right margin to leave some captured ships (fairly rare).
  4. The winning player has to have enough ships removed from the *first* fleet in the list to have that fleet entirely deleted, despite winning overall. (pretty darned rare).

Simply put, This didn’t happen to me once in testing. It hasn’t happened to many players either, as I understand it. And if it has happened to you… I may have good news :D

Patch and games sizes, onlive, bandwidth…

So OnLive is out in the UK. I noticed quite a few people on the interwebs pointing out that they won’t sign up because, like me, they are on limited bandwidth internet plans.

I live out in the country, where there isn’t as much choice of ISP as the cities, and because my business needs the net, I need a rock solid connection with reliability and really good telephone support, so I end up paying over the odds. As a result, I have very reliable broadband, pretty fast, but bandwidth capped to 45 gig /month. I generally never hit the limit, but then when I see a game demo thats 2 gigs, I normally just skip it.

Something that made me think about this was Heroes of Stalingrad, Red Orchestra. This game is a tech-support trainwreck, with numerous bugs, random crashes, occasional dissapearing sound effects, rubber-banding, blah blah. Underneath it all is a great game.

The good news is they keep patching the game (although often introduce more bugs than they fix). The bad news is the patches are normally 400MB+. Apparently the developers claim this is the unreal engines fault in some way, although I find that hard to believe. Almost all bugs in a game are in the .exe and the exe is rarely >20MB.  Regular 400MB patches are crazy.

I definitely think that big games studios totally forget about the ‘bandwidth-challenged’. It’s one thing to release big patches. It’s another thing to release such patches several times a month, and require the patch for online play. If everyone MUST have the latest version, don’t insist on chewing up over a gig or two a month of peoples bandwidth limit just to play a game.