The question of whether a computer can think is no more interesting than the question of whether a submarine can swim.
– Edsger Dijkstra
The design and architecture of game AI has long been one of my favorite subjects. AI is a peculiarly challenging and rewarding specialty of game design and programming, one that requires significant sophistication and inventiveness on the part of the designer. In addition to being critical to the success of any digital game, I believe a good understanding of AI patterns and methods makes one a better game designer across the board. Being able to think in the necessary abstractions to translate human analysis and decision-making into computer terms is hugely beneficial in crafting elegant, effective game systems. Particularly in complex games like strategy games, this ability is fundamental.
Learning to craft AI, however, can be difficult. Many AI resources I’ve encountered are difficult to really learn from. They tend to be esoteric, deal in theoretical situations or examples absent context, and can be hard to distill into their essential lessons such that you could readily make use of the learning in your own work. When I taught a course on programming AI at the University of Baltimore some years ago, I ran into a similar problem: to really learn AI, you have to be able to see it operating in a meaningful situation, and you have to be equipped to assess what you’re seeing and gauge its effectiveness. This is best done through practical demonstration, but that is even more difficult to find.
Therefore, I intend to undertake a series of articles and exercises focused on game AI from this practical perspective. My hope is that by working through the problems for my own edification, I can lend similar experience to readers and help illustrate how AI is actually, usefully achieved. My thought is to take a number of simple rulesets — some ordinary card games, for instance — and explore ways to craft AI to play them. Along the way we can see together how well some ideas work, when certain solutions are ideal and when they are not, and how to judge the suitability and effectiveness of game AI.
A word in preface: I will concern myself in this series with exploring AI design, meaning the techniques of representing appropriate player behavior in computer terms and the application of those techniques to real situations. While this process will be code-based, I am not going to focus overmuch on AI programming.
What is the difference? Primarily, it’s a question of optimization. Much of what consumes the work of game AI programming is keeping it smart while getting it to run cheap and fast. To do this is a difficult and time-consuming task, and in my experience always a custom-job to some extent: a particular AI’s optimization is mostly unique to its game and its circumstances. There are very talented engineers out there (and on my team) that do this much better than I, and I will not pretend greater expertise than they have. The code I will be writing and showing will instead be written for algorithmic clarity — arranged so that the operation and movement of the mechanisms are clear and easy to replicate in whatever codebase you need them in. This can, and probably will, mean that the code makes sub-optimal use of data storage, contains unnecessary redundancy or churn, and other sins of optimized code. This is by intention. While I will certainly endeavor to keep the processes as efficient and elegant as I can, I will leave off from that effort if doing so makes the algorithm under demonstration too difficult to see or understand.
As I go, I welcome comments, identification of errors and suggestions for improvements! I may not always have the free time to go back and repair inefficient code, but I will always fix bugs or mistakes and note any improvements that I did not get to implement myself.