// The following code contains unit test function that test the functionality
// of the above classes and functions.
// Tests for MinimMax search using NIM game as a domain.
// Test 1 checks that the terminal state of the game has no next moves.
function test1() {
let nim = new NIM([0, 0, 0], MiniMax.PLAYER1, MiniMax.PLAYER1);
nim.setNextMoves();
let actual = nim.next.map(nim => nim.toString()).join('\n');
let expected = '';
compareStringsAndReport('Test 1', actual, expected);
}
// Test 2 checks that the non-terminal state of the game has correct next moves.
function test2() {
let nim = new NIM([2, 2, 2], MiniMax.PLAYER1, MiniMax.PLAYER1);
nim.setNextMoves();
let actual = nim.next.map(nim => nim.toString()).join('\n');
let expected = '\
Map: 0,2,2\n\
Index: 0. Turn: player 2. Maximizer: player 1. Utility: 0. # of moves: 0\n\
Map: 1,2,2\n\
Index: 1. Turn: player 2. Maximizer: player 1. Utility: 0. # of moves: 0';
compareStringsAndReport('Test 2', actual, expected);
}
// Test 3 checks that the terminal state of the game is correctly identified as
// a winning state for the player whose turn it is, and as a non-winning state
// for the other player.
function test3() {
let nim1 = new NIM([0, 0, 0], MiniMax.PLAYER1, MiniMax.PLAYER1);
let winning1 = nim1.isWinner(MiniMax.PLAYER1);
let nim2 = new NIM([0, 0, 1], MiniMax.PLAYER1, MiniMax.PLAYER1);
let winning2 = nim2.isWinner(MiniMax.PLAYER1);
let actual = '' + winning1 + ' ' + winning2;
let expected = 'true false';
compareStringsAndReport('Test 3', actual, expected);
}
// Test 4 checks that a close to a terminal state of the game is correctly
// identified as a winning state.
function test4() {
let nim = new NIM([0, 1, 1], MiniMax.PLAYER1, MiniMax.PLAYER1, 0);
nim.run();
let actual = nim.toString();
let expected = '\
Map: 0,1,1\n\
Index: 0. Turn: player 1. Maximizer: player 1. Utility: 10. # of moves: 1';
compareStringsAndReport('Test 4', actual, expected);
}
// Test 5 checks that the MiniMax search correctly identifies the best move for
// both players.
function test5() {
let nim1 = new NIM([5, 5, 5], MiniMax.PLAYER1, MiniMax.PLAYER1, 0);
nim1.run();
let actual1 = nim1.getBest().toString();
let expected1= '\
Map: 0,5,5\n\
Index: 0. Turn: player 2. Maximizer: player 1. Utility: 10. # of moves: 5';
let nim2 = new NIM([0, 5, 5], MiniMax.PLAYER2, MiniMax.PLAYER2, 0);
nim2.run();
let actual2 = nim2.getBest().toString();
let expected2= '\
Map: 0,0,5\n\
Index: 0. Turn: player 1. Maximizer: player 2. Utility: -10. # of moves: 5';
let nim3 = new NIM([0, 0, 5], MiniMax.PLAYER1, MiniMax.PLAYER1, 0);
nim3.run();
let actual3 = nim3.getBest().toString();
let expected3= '\
Map: 0,0,1\n\
Index: 1. Turn: player 2. Maximizer: player 1. Utility: 10. # of moves: 1';
compareStringsAndReport('Test 5',
actual1 + '\n' + actual2 + '\n' + actual3,
expected1 + '\n' + expected2 + '\n' + expected3);
}
// Tests for MinimMax search using Tic-Tac-Toe game as a domain.
// Grid's elements
const x = MiniMax.PLAYER1;
const o = MiniMax.PLAYER2;
const _ = MiniMax.EMPTY;
// Test 6 checks that the terminal state of the game is correctly identified as
// a drawn state when the grid is full and there is no winner.
function test6() {
let tictactoe = new TicTacToe([
o, x, o,
o, x, o,
x, o, x
], o, o, 0);
tictactoe.run();
let actual = tictactoe.toString();
let expected = '\
Map:\n\
o x o\n\
o x o\n\
x o x\n\
Index: 0. Turn: player 2. Maximizer: player 2. Utility: 0. # of moves: 0';
compareStringsAndReport('Test 6', actual, expected);
}
// Test 7 checks that the terminal state of the game is correctly identified as
// a winning or non-winning state for players.
function test7() {
let tictactoe1 = new TicTacToe([
_, x, _,
_, x, _,
_, x, _ ], x, x, 1);
tictactoe1.run();
let actual1 = tictactoe1.toString();
let expected1 = '\
Map:\n\
_ x _\n\
_ x _\n\
_ x _\n\
Index: 1. Turn: player 1. Maximizer: player 1. Utility: 10. # of moves: 0';
let tictactoe2 = new TicTacToe([
_, _, _,
_, _, _,
o, o, o ], x, x, 2);
tictactoe2.run();
let actual2 = tictactoe2.toString();
let expected2 = '\
Map:\n\
_ _ _\n\
_ _ _\n\
o o o\n\
Index: 2. Turn: player 1. Maximizer: player 1. Utility: -10. # of moves: 0';
let tictactoe3 = new TicTacToe([
x, o, o,
o, x, o,
o, o, x ], o, x, 3);
tictactoe3.run();
let actual3 = tictactoe3.toString();
let expected3 = '\
Map:\n\
x o o\n\
o x o\n\
o o x\n\
Index: 3. Turn: player 2. Maximizer: player 1. Utility: 10. # of moves: 0';
let tictactoe4 = new TicTacToe([
x, x, o,
x, o, x,
o, x, x ], x, x, 4);
tictactoe4.run();
let actual4 = tictactoe4.toString();
let expected4 = '\
Map:\n\
x x o\n\
x o x\n\
o x x\n\
Index: 4. Turn: player 1. Maximizer: player 1. Utility: -10. # of moves: 0';
compareStringsAndReport('Test 7',
actual1 + '\n' + actual2 + '\n' + actual3 + '\n' + actual4,
expected1 + '\n' + expected2 + '\n' + expected3 + '\n' + expected4);
}
// Test 8 checks that a close to the terminal state of the game is correctly
// identified.
function test8() {
let tictactoe = new TicTacToe([
o, x, o,
x, _, x,
o, x, o ], o, x);
tictactoe.run();
let actual = tictactoe.next[0].toString();
let expected = '\
Map:\n\
o x o\n\
x o x\n\
o x o\n\
Index: 4. Turn: player 1. Maximizer: player 1. Utility: -10. # of moves: 0';
compareStringsAndReport('Test 8', actual, expected);
}
// Test 9 checks that the MiniMax search correctly identifies the next moves
// for the player.
function test9() {
let tictactoe = new TicTacToe([
o, x, o,
o, x, o,
_, _, _ ], o, o);
tictactoe.run();
let actual = tictactoe.next.map(tictactoe => tictactoe.toString()).join('\n');
let expected = '\
Map:\n\
o x o\n\
o x o\n\
o _ _\n\
Index: 6. Turn: player 1. Maximizer: player 2. Utility: 10. # of moves: 0\n\
Map:\n\
o x o\n\
o x o\n\
_ o _\n\
Index: 7. Turn: player 1. Maximizer: player 2. Utility: 10. # of moves: 2\n\
Map:\n\
o x o\n\
o x o\n\
_ _ o\n\
Index: 8. Turn: player 1. Maximizer: player 2. Utility: 10. # of moves: 0';
compareStringsAndReport('Test 9', actual, expected);
}
// Test 10 checks that the MiniMax search correctly evaluate the utility value
// of the initial state of the game.
function test10() {
let tictactoe = new TicTacToe([
_, _, _,
_, _, _,
_, _, _ ], x, x, 0);
tictactoe.run();
let actual = tictactoe.toString();
let expected = '\
Map:\n\
_ _ _\n\
_ _ _\n\
_ _ _\n\
Index: 0. Turn: player 1. Maximizer: player 1. Utility: 0. # of moves: 9';
compareStringsAndReport('Test 10', actual, expected);
}