IMPLEMENTATION AND TESTING
5.1 Implementation
The program can be played immediately after opening it. By default, the
user is playing against white with medium difficulty. The user can change the
setting by selecting the desired disc side and difficulty in the bottom right corner
of the program. The restart button is used to restart the game.
Basic information about the current game state is saved in object named
Board. Board contains game state and various utilities, such as disc counter, move
generator, move validator, move executor, and game status checker. Move
12
the board).
Move generator is mainly used in computer’s turn. After getting the
current game moves, the program starts building the tree. The current game state
is stored in an object called Node and placed in root. Then, the program generates
root’s possible moves, saves each of them in Node, places them in the tree as the
child of the parent (root). Tree building process depends on difficulty level. Easy
yields depth 4 tree, medium yields 6 depth tree, hard yields 8 depth tree.
Table 5.1: Move Generation Result Table
4
The result of the move generation is represented by Table 5.1. Root has 4
childs, the next depth each has 3 childs, and so on. In total, with medium difficulty
setting, the tree data structure has 195 leaf nodes and 267 nodes. In regards to
Negascout searching algorithm, the program needs to evaluate at least half of the
leaf nodes, due to pruning, and get the best value and the best node.
Function createChild() is used to create child using generateMove()
methods that available in Board. The function requires current game state. The
code is demonstrated below.
4. if(parent.getData().getCountMoves()>0)
5. {
6. int [][] move = parent.getData().getMoves();
7. int countMove = parent.getData().getCountMoves();
8. for(int i=0;i<countMove;i++)
9. {
10. Node newNode = new Node(parent);
11. newNode.getData().placeDisc(move[i][0],move[i]
19. Node temp = parent.getChild();
20. while(temp.getNextSibling()!=null)
Using the code above, the program creates every child with the parent as
an input parameter. The program needs to generate move first and get the number
of possible moves first. Then the program clones the parent, do the possible
moves, and assigns them to the tree.
Negascout algorithm as a search tree involves in searching and pruning of
the tree. Negascout search code is demonstrated below. Negascout is created as a
recursive function and called with negaScout(root, -9999, 9999, maxDepth) at
first. Root contains the current game state. Variable maxDepth depends on
difficulty level. Variable alpha is set to -9999 as default because alpha is used to
search the maximum value, hence any evaluation result will be bigger than -9999.
Evaluator.calculateScore() in line 6 will return an integer value of evaluation
score. Line 31 and 32 is used to prune tree if alpha>=beta. Pruning method is the
1. public int negaScout(Node parent,int alpha,int beta,int depth) 2. {
3. int score=0, n, moves, cur;
4. Node temp = parent;
5. if(depth == 0 || parent.getChild() == null)
6. return Evaluator.calculateScore(parent.getData());
7. else
8. {
9. score = -9999;
10. n = beta;
11. moves = temp.getData().getCountMoves();
12. for(int i=0;i<moves;i++)
13. {
14. if(i==0)
15. temp = temp.getChild();
16. else
17. temp = temp.getNextSibling();
18. cur= -negaScout(temp,-n,-alpha,depth-1);
19. if(cur > score)
20. {
21. if(n == beta || depth < 1)
22. {
23. score = cur;
24. bestMove = temp;
25. }
26. else
27.
score=-negaScout(temp,-beta,-cur,depth-1);
28. }
29. if(score > alpha)
30. alpha = score;
31. if(alpha >= beta)
32. return alpha;
The program also has to build the game structure itself. The game structure
consists of managing turn for each player and checking if the game is over. Turn
management also in charge of awaiting input from player and artificial
intelligence. The game is over if all squares were filled or there is no possible
moves for both players The game also restarts if user press restart button or new
As seen in line 79, the game itself is a loop as long as the game is not over
or there is no restart command. Function turnGame() itself contains 2 times loop.
At first, turnGame() check if there are possible moves. If there are no possible
moves, the game pass turns to the other player. Then, the game checks the turn. If
it is user turn, the game will wait for input from the user. If it is computer turn, the
game will do tree building and Negascout search. The game will change the game
state by placing the move to the board.
5.2 Testing
The program displays an initial board at first. By default, the user will play
as black’s side and facing easy difficulty. Program will continue to wait for input
when it’s user’s turn. After receiving an input from user, the program executes the
move and waits for artificial intelligence input. Program will build a move tree,
search for the best state, and continue waiting until search process is done.
The resource usage depends on the difficulty level. For example, hard
dificulty level tree moves will have more nodes than medium difficulty level tree
moves. Although Negascout search algorithm will not visit each tree, the sheer
number of the nodes will affects the memory usage. The graph for the searched
node can be seen below:
As seen above, the searched node, in hard difficulty setting, reachs more
than sixty thousands nodes. Thus the memory usage in hard difficulty will be
significantly higher than the memory usage in medium difficulty. The actual
resource usage can be seen in the graph below.
Illustration 5.3: Searched Node Comparison Graph Based on Difficulty Level
0 200 400 600 800 1000 1200 1400 1600
Memory Usage Comparison
based on Difficulty Settings
easy medium hard
Difficulty
M
e
m
o
ry
(MB
)
happening because of the tree size. Although Negascout won’t visit every nodes,
created nodes affects memory usage.
The game itself is run in laptop with Core i5 4200M as the processor. The
processor usage is displayed with the graph below.
The pruning process built in Negascout itself is quite efficient in hard
difficulty. The actual node searched in Negascout is less than ten percent of the
node count in moves tree. As seen in the graphs below, pruning efficiency will
depends on the node count. 0.00%
based on Difficulty Settings
easy
Illustration 5.5: Processor Usage Comparison based on Difficulty Setting
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29
0 500000 1000000 1500000
Node Comparison in Hard Diffiulty
Negascout Pruning Capabilities
Negascout itself is quite effective in searching in the tree structure.
Although Negascout have to search ~150.000 nodes (after pruning), the search
process itself only needs ~4 seconds in hard difficulty setting. The time needed in
search process can be seen in the graph below. As seen in the graph below, the
search process took considerable amount of time in hard difficulty setting. There
is abysmal differences in search process time in medium and easy difficulty
Time Comparison based on Difficulty
easy