Wednesday, January 14, 2009

The simplest AI in C#

Creating board games on the computer is easy, creating an opponent to play the game against is hard.

A lot of us programmers out there are also board game enthusiasts. We would like nothing better than to sit down in front of the computer and spend a few hours out maneuvering some truly diabolical AI opponents. Whether it’s crushing the Axis in Axis and Allies, dominating Europe in Diplomacy or simply enjoying a quick game of world conquest in Risk, we get to enjoy our favorite board games without the need to coordinate a date and time with up to five or six of your friends. Even when you can take on each other online, sometimes getting everyone together is harder than winning the games you wish to play.

Well with a good AI, all your games become playable by yourself and with a great AI, they become obsessive as you try to, at first barley hold your own and later to finally dominate these awesome challengers. Yet, how are these opponents created? Other than creating a completely random opponent, writing an AI to play a board game at a high level is one of the hardest things in programming you could do.

Which brings me to my point: I’m not going to show you how to create a diabolical AI opponent. I’m not even going to say if I even know how to. What I want to show you though, is how to take that first step in writing AI’s, by creating what could possibly be the simplest AI opponent ever … for the game of “Rock, paper and scissors”.

There are many types of AI opponents, but in “Rock, paper and scissors” the only type of opponent is one that tries to predict his opponent’s next move. So let’s create a predictive AI.

What is the one piece of data that a predictive AI needs to calculate a decision? His opponents’ prior moves. So, as play of “Rock, paper and scissors” continues, we will need to accumulate the human player’s prior moves. The easiest way to do that is to hold them in a string, each character (‘R’, ‘P’ or ‘S’) representing a move.

To keep it simple, my AI will look for three move patterns. It will take the last two moves off the end of the string and add each of the three possible moves, in turn, on the end and do a string search to find how many times the human opponent played the same three move pattern previously. The IA will assume that the pattern with the highest count will be the one the human plays and will choose the move to beat it. If there was a tie (Even if that it is a tie of zero count for all three possible patterns) a move is picked randomly among the tied choices. Just to through a bit of confusion in, 10% of the time, the AI’s move will be completely random.

Now, this AI is by no means unbeatable, but playing against it in a race for the first to win 100 games, it is a very tough opponent, just like AI opponents should be.

The complete code for a console application implementing the “Rock, paper and scissors” AI can be downloaded here.

No comments: