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.
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
Players are connected.
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.
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
VirtualPlayerComplex classes. It is used only in Windows version and does not bring any real performance improvements.
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.