package aima.test.core.unit.environment.tictactoe;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import aima.core.environment.tictactoe.TicTacToeGame;
import aima.core.environment.tictactoe.TicTacToeState;
import aima.core.search.adversarial.AlphaBetaSearch;
import aima.core.search.adversarial.IterativeDeepeningAlphaBetaSearch;
import aima.core.search.adversarial.MinimaxSearch;
import aima.core.util.datastructure.XYLocation;
/**
* @author Ruediger Lunde
*
*/
public class TicTacToeTest {
private TicTacToeGame game;
private TicTacToeState state;
private double epsilon = 0.0001;
@Before
public void setUp() {
game = new TicTacToeGame();
state = game.getInitialState();
}
@Test
public void testCreation() {
game = new TicTacToeGame();
state = game.getInitialState();
Assert.assertEquals(9, game.getActions(state).size());
Assert.assertEquals(TicTacToeState.X, game.getPlayer(state));
}
@Test
public void testHashCode() {
TicTacToeState initialState1 = game.getInitialState();
TicTacToeState initialState2 = game.getInitialState();
Assert.assertEquals(initialState1.hashCode(), initialState2.hashCode());
TicTacToeState state1 = game.getResult(initialState1, new XYLocation(0, 0));
Assert.assertNotSame(state1.hashCode(), initialState2.hashCode());
TicTacToeState state2 = game.getResult(initialState2, new XYLocation(0, 0));
Assert.assertEquals(state1.hashCode(), state2.hashCode());
}
@Test
public void testOnCreationBoardIsEmpty() {
Assert.assertEquals(TicTacToeState.EMPTY, state.getValue(0, 0));
Assert.assertEquals(TicTacToeState.EMPTY, state.getValue(0, 2));
Assert.assertEquals(TicTacToeState.EMPTY, state.getValue(2, 0));
Assert.assertEquals(TicTacToeState.EMPTY, state.getValue(2, 2));
Assert.assertEquals(true, state.isEmpty(0, 0));
Assert.assertEquals(true, state.isEmpty(2, 2));
}
@Test
public void testMakingOneMoveChangesState() {
state = game.getResult(state, new XYLocation(0, 0));
Assert.assertEquals(TicTacToeState.X, state.getValue(0, 0));
Assert.assertEquals(false, state.isEmpty(0, 0));
Assert.assertEquals(8, game.getActions(state).size());
Assert.assertEquals(TicTacToeState.O, game.getPlayer(state));
}
@Test
public void testMakingTwoMovesChangesState() {
state = game.getResult(state, new XYLocation(0, 0));
state = game.getResult(state, new XYLocation(0, 1));
Assert.assertEquals(TicTacToeState.O, state.getValue(0, 1));
Assert.assertEquals(false, state.isEmpty(0, 1));
Assert.assertEquals(true, state.isEmpty(1, 0));
Assert.assertEquals(7, game.getActions(state).size());
Assert.assertEquals(TicTacToeState.X, game.getPlayer(state));
}
@Test
public void testVerticalLineThroughBoard() {
state.mark(0, 0);
state.mark(1, 0);
state.mark(0, 1);
state.mark(1, 1);
Assert.assertEquals(false, state.lineThroughBoard());
state.mark(new XYLocation(0, 2));
Assert.assertEquals(true, state.lineThroughBoard());
}
@Test
public void testHorizontalLineThroughBoard() {
state.mark(0, 0);
state.mark(0, 1);
state.mark(1, 0);
state.mark(1, 1);
Assert.assertEquals(false, state.lineThroughBoard());
state.mark(2, 0);
Assert.assertEquals(true, state.lineThroughBoard());
}
@Test
public void testDiagonalLineThroughBoard() {
state.mark(0, 0);
state.mark(0, 1);
state.mark(1, 1);
state.mark(0, 2);
Assert.assertEquals(false, state.lineThroughBoard());
state.mark(2, 2);
Assert.assertEquals(true, state.lineThroughBoard());
}
@Test
public void testMinmaxValueCalculation() {
MinimaxSearch<TicTacToeState, XYLocation, String> search = MinimaxSearch
.createFor(game);
Assert.assertTrue(epsilon > Math.abs(search.maxValue(state,
TicTacToeState.X) - 0.5));
Assert.assertTrue(epsilon > Math.abs(search.minValue(state,
TicTacToeState.O) - 0.5));
// x o x
// o o x
// - - -
// next move: x
state.mark(0, 0); // x
state.mark(1, 0); // o
state.mark(2, 0); // x
state.mark(0, 1); // o
state.mark(2, 1); // x
state.mark(1, 1); // o
Assert.assertTrue(epsilon > Math.abs(search.maxValue(state,
TicTacToeState.X) - 1));
Assert.assertTrue(epsilon > Math.abs(search.minValue(state,
TicTacToeState.O)));
XYLocation action = search.makeDecision(state);
Assert.assertEquals(new XYLocation(2, 2), action);
}
@Test
public void testMinmaxDecision() {
MinimaxSearch<TicTacToeState, XYLocation, String> search = MinimaxSearch
.createFor(game);
search.makeDecision(state);
int expandedNodes = search.getMetrics().getInt("expandedNodes");
Assert.assertEquals(549945, expandedNodes);
}
@Test
public void testAlphaBetaDecision() {
AlphaBetaSearch<TicTacToeState, XYLocation, String> search = AlphaBetaSearch
.createFor(game);
search.makeDecision(state);
int expandedNodes = search.getMetrics().getInt("expandedNodes");
Assert.assertEquals(30709, expandedNodes);
}
@Test
public void testIterativeDeepeningAlphaBetaDecision() {
IterativeDeepeningAlphaBetaSearch<TicTacToeState, XYLocation, String> search = IterativeDeepeningAlphaBetaSearch
.createFor(game, 0.0, 1.0, 100);
search.makeDecision(state);
int expandedNodes = search.getMetrics().getInt("expandedNodes");
Assert.assertEquals(76035, expandedNodes);
}
}