Introduction
My initial goal was to port Reversi in C# By BrainJar program to Pocket PC. After some time, I realized that without understanding what and how it happens, there is no chance to make use of the existing program. So, I wrote it myself. I have tried to make it as simple as possible.
The whole game functionality is concentrated in the independent assembly gma.Reversi.dll. There are two different Presentation Layers using the same assembly; the gma.Windows.Reversi
for Windows .NET and gam.Mobile.Reversi
for PocketPC CF.
The Board
class is used to store game information, maintain statistics which are necessary for evaluation, and guarantees game rules. The VirtualPlayer
class is a descendant of the Player
class and includes evaluation and search algorithms. This is a class that implements "intelligence" to this program. The GUIPlayer
class is also descendant of Player
and implements interaction with the presentation layer. Both players are interacting with board using same Methods and Events, so there is no difference for Board
about which Player
s are connected.
Game Theory
Very good page to understand programming a Reversi game is "Writing an Othello program" by Gunnar Andersson. Following information will be interesting only if you are familiar with the basics of strategic game programming.
Searching
The core of a game is alpha-beta pruning algorithm. My implementation is relatively universal, so it can be used in some other board games as well. I am going to use it in my GO game I am working on currently. Initially, I have implemented brutal minimax search, and after rewriting it into alpha-beta, I had a 70% increase of performance. A heuristic to perform shallow searches was implemented only in VirtualPlayerComplex
class, it is basically the only difference between VirtualPlayer
and VirtualPlayerComplex
classes. It is used only in Windows version and does not bring any real performance improvements.
Position evaluation
This description gives you only an idea of how it works; in some cases, it is a little bit complicated. My evaluation function (Score
) is based on the following criteria:
- Dominance. It is good to own squares as an opponent.
- Mobility. It is good when you have more move alternatives.
- Disk-square table. Corners are good and the squares next to corners are bad.
- Stability. It is good to capture squares which cannot be converted.
I have assigned some weights to these criteria, but I am sure that verifying them can increase the program's "intelligence".
There are a lot of things to do in order to increase performance (and accordingly search depth), but then you need to make a compromise between performance and code transparency. This program was not written to win Othello world cup, so there are many ways to improve it. For example, Background Analysis (a thread that calculates next moves when a program is waiting for an input from the human player), Knowledge Base for game openings, and Pattern evaluation.