Reversi is a board game for two players, played in turns. It is implemented here in Angular 2, with the option to set each player as a human player or a computer player.
This project was initially generated with Angular CLI version 1.2.0.
Run ng serve
(or npm start
) for a dev server. Navigate to http://localhost:4200/
. The app will automatically reload if you change any of the source files.
Run ng generate component component-name
to generate a new component. You can also use ng generate directive|pipe|service|class|module
.
Run ng build
to build the project. The build artifacts will be stored in the dist/
directory. Use the --prod
flag for a production build.
I didn't write tests yet, but I kept the ones that were automatically generated by Angular CLI.
Run ng test
to execute the unit tests via Karma.
Run ng e2e
to execute the end-to-end tests via Protractor.
Before running the tests make sure you are serving the app via ng serve
.
The game is deployed to GitHub Pages, under the url https://yonih.github.io/reversi-angular2/. To deploy, I used angular-cli-ghpages v0.5.1 (consult documentation for more details).
To get more help on the Angular CLI use ng help
or go check out the Angular CLI README.
Reversi is a Zero-Sum Game. A classic AI algorithm for two-player zero-sum games is Minmax. For the computer player I used the Alpha-Beta algorithm, which is an optimized version of Minmax.
Here's a very high-level description of how it works:
-
When it's the computer's turn, the algorithm constructs a game tree for a limited number of levels. This is how the computer "sees moves ahead". However, seeing more than a few moves ahead is not practical since the number of nodes in the tree grows exponentially with the number of the tree levels. Constructing a complete game tree would take just about forever, and so after a few levels, the construction stops and the farthest future boards (the tree leaves) are examined.
-
On each of those future boards, the algorithm calls a heuristic function, which evaluates the board and returns a number estimating how good or bad it is for each player:
- A positive number means that the black player leads. A greater number means greater advantage. Infinity means victory for the black.
- A negative number means that the white player leads. A greater number (in absolute value) means greater advantage. Minus inifinity means victory for the white.
- Zero means tie.
This function is the core of the computer player's artificial intelligence. It is also the only part that is specific to a particular game (Reversi in this case). A Chess computer player may be implemented by applying the same algorithm, only with a different heuristic function that is suitable for Chess.
-
The numbers returned by the function are then assigned up the tree, assuming that each player always chooses the best possible move for them. When the root is assigned, it is known what is the branch (move) that will lead to the estimated-best future board, and so that move is chosen. A detailed example of that final stage can be found here.
The heuristic function in this implementation generally works like this:
- A winning board is ofcourse the best board, and it's better to win by the biggest possible difference.
- Corners are very important in Reversi. A board is very good for a player if the player has taken more corners than the opponent.
- In the beginning of a game it's good to have less pieces, but later on it's better to have more.