/*
* Copyright 2015 S. Webber
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.oakgp.examples.tictactoe;
import static org.oakgp.Type.type;
import org.junit.Test;
import org.oakgp.Assignments;
import org.oakgp.Type;
import org.oakgp.function.Function;
import org.oakgp.function.choice.If;
import org.oakgp.function.choice.OrElse;
import org.oakgp.node.ConstantNode;
import org.oakgp.node.Node;
import org.oakgp.rank.fitness.FitnessFunction;
import org.oakgp.rank.tournament.FirstPlayerAdvantageGame;
import org.oakgp.rank.tournament.TwoPlayerGame;
import org.oakgp.util.DummyNode;
import org.oakgp.util.RunBuilder;
import org.oakgp.util.Utils;
public class TicTacToeSystemTest {
private static final int NUM_GENERATIONS = 10;
private static final int INITIAL_POPULATION_SIZE = 50;
private static final int INITIAL_POPULATION_MAX_DEPTH = 4;
private static final Type BOARD_TYPE = type("board");
private static final Type MOVE_TYPE = type("move");
private static final Type POSSIBLE_MOVE = type("possibleMove");
private static final Type SYMBOL_TYPE = type("symbol");
private static final Type[] VARIABLE_TYPES = { BOARD_TYPE, SYMBOL_TYPE, SYMBOL_TYPE };
@Test
public void testHighLevel() {
Function[] functions = { new GetPossibleMove("corner", Board::getFreeCorner), new GetPossibleMove("centre", Board::getFreeCentre),
new GetPossibleMove("side", Board::getFreeSide), new GetWinningMove(), new GetAnyMove(), new OrElse(MOVE_TYPE) };
TwoPlayerGame game = createTicTacToeGame();
new RunBuilder().setReturnType(MOVE_TYPE).setConstants().setVariables(VARIABLE_TYPES).setFunctions(functions).setTwoPlayerGame(game)
.setInitialPopulationSize(INITIAL_POPULATION_SIZE).setTreeDepth(INITIAL_POPULATION_MAX_DEPTH).setMaxGenerations(NUM_GENERATIONS).process();
}
@Test
public void testLowLevelTournament() {
Function[] functions = { new IsFree(), new IsOccupied(), new GetAnyMove(), new IfValidMove(), new OrElse(MOVE_TYPE), new And(), new If(POSSIBLE_MOVE) };
ConstantNode[] constants = getMoveConstants();
TwoPlayerGame game = createTicTacToeGame();
new RunBuilder().setReturnType(MOVE_TYPE).setConstants(constants).setVariables(VARIABLE_TYPES).setFunctions(functions).setTwoPlayerGame(game)
.setInitialPopulationSize(INITIAL_POPULATION_SIZE).setTreeDepth(INITIAL_POPULATION_MAX_DEPTH).setMaxGenerations(NUM_GENERATIONS).process();
}
@Test
public void testLowLevelFitnessFunction() {
Function[] functions = { new IsFree(), new IsOccupied(), new GetAnyMove(), new IfValidMove(), new OrElse(MOVE_TYPE), new And(), new If(POSSIBLE_MOVE) };
ConstantNode[] constants = getMoveConstants();
TicTacToeFitnessFunction fitnessFunction = new TicTacToeFitnessFunction();
new RunBuilder().setReturnType(MOVE_TYPE).setConstants(constants).setVariables(VARIABLE_TYPES).setFunctions(functions)
.setFitnessFunction(fitnessFunction).setInitialPopulationSize(INITIAL_POPULATION_SIZE).setTreeDepth(INITIAL_POPULATION_MAX_DEPTH)
.setMaxGenerations(NUM_GENERATIONS).process();
}
private ConstantNode[] getMoveConstants() {
return Utils.createEnumConstants(Move.class, POSSIBLE_MOVE);
}
private TwoPlayerGame createTicTacToeGame() {
return new FirstPlayerAdvantageGame(new TicTacToe());
}
private class TicTacToeFitnessFunction implements FitnessFunction {
private TicTacToe ticTacToe = new TicTacToe();
private Node[] ais = new Node[] {//
new DummyNode() {
@Override
public Move evaluate(Assignments assignments) {
Board board = (Board) assignments.get(0);
return board.getFreeMove();
}
}, new DummyNode() {
@Override
public Move evaluate(Assignments assignments) {
Board board = (Board) assignments.get(0);
Move nextMove = board.getWinningMove(Symbol.X);
if (nextMove == null) {
nextMove = board.getFreeMove();
}
return nextMove;
}
}, new DummyNode() {
@Override
public Move evaluate(Assignments assignments) {
Board board = (Board) assignments.get(0);
Move nextMove = board.getWinningMove(Symbol.O);
if (nextMove == null) {
nextMove = board.getFreeMove();
}
return nextMove;
}
}, new DummyNode() {
@Override
public Move evaluate(Assignments assignments) {
Board board = (Board) assignments.get(0);
Move nextMove = board.getWinningMove(Symbol.X);
if (nextMove == null) {
nextMove = board.getWinningMove(Symbol.O);
}
if (nextMove == null) {
nextMove = board.getFreeCorner();
}
if (nextMove == null) {
nextMove = board.getFreeCentre();
}
if (nextMove == null) {
nextMove = board.getFreeMove();
}
return nextMove;
}
}, new DummyNode() {
@Override
public Move evaluate(Assignments assignments) {
Board board = (Board) assignments.get(0);
Move nextMove = board.getWinningMove(Symbol.X);
if (nextMove == null) {
nextMove = board.getWinningMove(Symbol.O);
}
if (nextMove == null) {
nextMove = board.getFreeCorner();
}
if (nextMove == null) {
nextMove = board.getFreeCentre();
}
if (nextMove == null) {
nextMove = board.getFreeMove();
}
return nextMove;
}
} };
@Override
public double evaluate(Node candidate) {
int result = 0;
for (Node ai : ais) {
result += ticTacToe.evaluate(ai, candidate);
}
return result;
}
}
}