package de.tu_dresden.inf.ggp06_2.strategies; import java.util.*; import de.tu_dresden.inf.ggp06_2.resolver.Atom; import de.tu_dresden.inf.ggp06_2.resolver.Predicate; import de.tu_dresden.inf.ggp06_2.resolver.Const; import de.tu_dresden.inf.ggp06_2.resolver.Expression; import de.tu_dresden.inf.ggp06_2.resolver.ExpressionList; import de.tu_dresden.inf.ggp06_2.resolver.Variable; import de.tu_dresden.inf.ggp06_2.resolver.fuzzy.FuzzyResolution; import de.tu_dresden.inf.ggp06_2.resolver.fuzzy.FuzzySubstitution; import de.tu_dresden.inf.ggp06_2.resolver.scope.GameStateScope; import de.tu_dresden.inf.ggp06_2.resolver.structures.GameNode; import de.tu_dresden.inf.ggp06_2.resolver.structures.GameState; import de.tu_dresden.inf.ggp06_2.simulator.Game; import de.tu_dresden.inf.ggp06_2.simulator.flags.TimerFlag; import de.tu_dresden.inf.ggp06_2.strategies.mixins.StrategyMixin; public class TurnTakingFuzzySearch extends AbstractStrategy{ private final FuzzySubstitution empty = new FuzzySubstitution(); private final List<Expression> guard = new ArrayList<Expression>(); private TimerFlag flag; private int depthTreshold = 6; private Map<ExpressionList, Long> historyHeuristic; private int depthIncrement = 1; private int initialDepth = 0; private int availableBoosts = 5; private int ourTurn; private int numberOfPlayers; private StrategyMixin mixin; public TurnTakingFuzzySearch(Game game, String role, StrategyMixin mixin){ super(game,role); historyHeuristic = new HashMap<ExpressionList, Long>(); flag = new TimerFlag(); //ourTurn = this.game.getOwnTurn(this.role); ourTurn = 1; numberOfPlayers = this.game.getRoleNames().size(); this.mixin = mixin; } public TurnTakingFuzzySearch(Game game, String role, StrategyMixin mixin, TimerFlag flag){ this(game, role, mixin); this.timerFlag = flag; } @Override public Expression pickMove(GameNode node){ return doTheSearch( node ); } /*private Expression doTheSearch(GameNode node) { double tmpChildValue, bestChildNodeValue = -1; Expression bestDirectMove = new Predicate(Const.aDoes, role, Const.aNoop); ExpressionList legalMoves; try { legalMoves = this.game.getLegalMoves( this.role, node.getState(), this.flag); } catch ( InterruptedException e ) { return bestDirectMove; } int incr = 0; while (incr < 40 ){ Set<Expression> moves = new HashSet<Expression>(); moves.addAll( legalMoves ); while( ! moves.isEmpty()){ Expression aMove = extractMoveAccordingToHH(moves); try { GameNode nextNode = this.game.produceNextNode( node, new ExpressionList(aMove), timerFlag ); tmpChildValue = doSearchIteration(nextNode, initialDepth+incr); //logger.info( "tmpChildValue: "+tmpChildValue+" for "+nextNode+" to depth "+(initialDepth+incr) ); } catch (InterruptedException ex) { return bestDirectMove; } if (tmpChildValue > bestChildNodeValue){ bestChildNodeValue = tmpChildValue; bestDirectMove = aMove; if (1.0 == bestChildNodeValue){ return bestDirectMove; } } } incr++; updateHistoryHeuristic( bestDirectMove, availableBoosts*(initialDepth + 1)); } return bestDirectMove; } */ private Expression doTheSearch(GameNode node) { Expression bestDirectMove; try{ ExpressionList moves = this.game.getLegalMoves( role, node.getState(), timerFlag ); if ( moves.size() == 1 ) return moves.get(0); bestDirectMove = moves.get( random.nextInt(moves.size()) ); } catch (InterruptedException ex) { System.err.println("Timer Interrupt"); return new Predicate(Const.aDoes, role, Const.aNoop); } int incr = 1; double nodeValue =0.0; while ( !(nodeValue == 1.0) ){ try{ for(GameNode aNode : this.game.stateTree.getChildren( node )){ if(aNode.getNodeValue() == node.getNodeValue()){ bestDirectMove = aNode.getMoves().get( 0 ); break; } } nodeValue = doSearchIteration(node, incr*depthIncrement, -1000.0, 1000.0); //logger.info( ""+this.game.stateTree ); //logger.info( "tmpChildValue: "+tmpChildValue+" for "+nextNode+" to depth "+(initialDepth+incr) ); for(GameNode aNode : this.game.stateTree.getChildren( node )){ if(aNode.getNodeValue() == node.getNodeValue()){ bestDirectMove = aNode.getMoves().get( 0 ); break; } } } catch (InterruptedException ex) { return bestDirectMove; } incr++; } return bestDirectMove; } private double doSearchIteration( GameNode node, int depth, double alpha, double beta) throws InterruptedException { double value = 0.0; if(node.getNodeValue() == 1.0){ return 1.0; } if (node.getState().isTerminal()){ //logger.info( " terminal case " ); value = heurisicValue(node); storeNodeValue(node, depth, value); //} else if (wasPriorVisited(node)) { // value = priorValue(node); } else if (0 == depth){ //logger.info( " 0==depth case " ); value = heurisicValue(node); storeNodeValue(node, depth, value); } else { Set<ExpressionList> moves = new HashSet<ExpressionList>(); List<ExpressionList> legalMoves = this.game.getCombinedLegalMoves( node.getState(), this.flag); moves.addAll( legalMoves ); // value = processAvailableMoves( node, depth, moves, legalMoves, alpha, beta ); double tmpValue, currentBest = -2000.0; ExpressionList currentBestMove = legalMoves.get( 0 ); int childOrder = moves.size(); while( ! moves.isEmpty()){ ExpressionList aMove = extractMoveAccordingToHH(moves); GameNode nextNode = this.game.produceNextNode( node, aMove, this.timerFlag ); boolean boostingPerformed = false; if ( depth == 1 && node.getDepth() > this.depthTreshold && availableBoosts > 0){ depth = childOrder*initialDepth; availableBoosts--; boostingPerformed = true; //logger.info(" boosting! "); } if (((node.getDepth() % numberOfPlayers == ourTurn) || (node.getDepth() % numberOfPlayers == (ourTurn-1+numberOfPlayers)%numberOfPlayers)) && (node.getDepth() > 0)){ tmpValue = - doSearchIteration( nextNode, depth-1, -beta, -alpha ); }else{ tmpValue = doSearchIteration( nextNode, depth-1, alpha, beta ); } /* i = (i>0)? i-1: 0; if (result > score) score = result; if (score >= beta){ bestMove = key; break; } alpha = (alpha > score)? alpha : score; } */ //logger.info( "tmpValue: "+tmpValue ); if ( boostingPerformed ){ availableBoosts++; } if ( tmpValue > currentBest ){ currentBest = tmpValue; } if (currentBest >= beta){ currentBestMove = aMove; break; } alpha = (alpha > currentBest)? alpha : currentBest; childOrder--; } node.getState().setFuzzyValueForRole( role, currentBest ); updateHistoryHeuristic(currentBestMove, depth*availableBoosts); value = currentBest; if (depth == initialDepth) { //logger.info( " expansion case for : "+depth+" value "+value ); } storeNodeValue(node, depth, value); } //logger.info( node ); return value; } private void storeNodeValue(GameNode node, int depth, double value) { node.setSearchDepth( depth ); node.setNodeValue( value ); } private ExpressionList extractMoveAccordingToHH(Set<ExpressionList> moves) { Iterator<ExpressionList> iter = moves.iterator(); ExpressionList extractedMove = iter.next(); long hhValueOfExtractedMove = (historyHeuristic.containsKey( extractedMove )) ? historyHeuristic.get( extractedMove ) : 0; while (iter.hasNext()){ ExpressionList iteratedMove = iter.next(); if (historyHeuristic.containsKey( iteratedMove )){ long hhValueOfIteratedMove = historyHeuristic.get( iteratedMove ); if (hhValueOfExtractedMove < hhValueOfIteratedMove){ extractedMove = iteratedMove; hhValueOfExtractedMove = hhValueOfIteratedMove; } } } moves.remove( extractedMove ); return extractedMove; } private void updateHistoryHeuristic(ExpressionList currentBestMove, int importance) { long increment = Math.round( Math.pow( importance, 2 ) ); if (historyHeuristic.containsKey( currentBestMove )){ long i = historyHeuristic.get( currentBestMove ); historyHeuristic.put( currentBestMove, i+increment ); } else { historyHeuristic.put(currentBestMove, increment); } } private double heurisicValue(GameNode node) throws InterruptedException{ GameState state = node.getState(); if (timerFlag.interrupted()) throw new InterruptedException(); double terminalFuzzyValue = 0.0; // First of all get terminal value, which does not // depend on any role GameStateScope scope = new GameStateScope(game.getTheory(), state); FuzzyResolution terminal = Const.aTerm.fuzzyEvaluate( empty, scope, guard, timerFlag); terminalFuzzyValue = terminal.getFuzzyValue(); // Then evaluate current state for our role if (!state.containsFuzzyValueForRole( role )){ double fuzzyValue = fuzzyEvaluateStateForRole(role, state, scope, terminalFuzzyValue); state.setFuzzyValueForRole( role, fuzzyValue ); state.flushFuzzyMemorizations(); return fuzzyValue; } return state.getFuzzyValueForRole( role ); } private double fuzzyEvaluateStateForRole( Atom role, GameState state, GameStateScope scope, double terminalFuzzyValue) throws InterruptedException { List<Predicate> goals = game.getGoalsForRole( role ); double allGoalValues = 0; double allGoalsFuzzyValues = 0; for(Predicate aGoal : goals) { Expression eGoalValue = aGoal.getOperands().get( 1 ); if ( eGoalValue instanceof Atom ) { Atom aGoalValue = (Atom) eGoalValue; int value = Integer.parseInt( aGoalValue.toString() ); if ( 0 != value ){ allGoalValues += value; double oneGoalFuzzyValue = evaluateOneGoal( role, state, scope, terminalFuzzyValue, aGoal, value ); oneGoalFuzzyValue = oneGoalFuzzyValue * value * 0.01; allGoalsFuzzyValues = (0 == allGoalsFuzzyValues ) ? oneGoalFuzzyValue : Expression.tConorm( allGoalsFuzzyValues, oneGoalFuzzyValue ); } } else if (eGoalValue instanceof Variable){ mixin.preStateEvaluation(state, game, timerFlag); FuzzyResolution resolution = aGoal.fuzzyEvaluate( empty, scope, guard, timerFlag); for(FuzzySubstitution aSub : resolution){ Predicate newGoal = (Predicate) aGoal.apply( aSub ); Expression aNewGoalValue = newGoal.getOperands().get( 1 ); if (aNewGoalValue instanceof Atom){ Atom aGoalValue = (Atom) aNewGoalValue; int value = Integer.parseInt( aGoalValue.toString() ); if ( 0 != value ){ allGoalValues += value; double oneGoalFuzzyValue = aSub.getFuzzyValue(); if (state.isRoleGoalValue( role ) && state.getRoleGoalValue( role ) == value) { oneGoalFuzzyValue = Expression.tConorm( oneGoalFuzzyValue, terminalFuzzyValue ); } else { oneGoalFuzzyValue = Expression.tNorm( oneGoalFuzzyValue, terminalFuzzyValue ); } oneGoalFuzzyValue = oneGoalFuzzyValue * value * 0.01; allGoalsFuzzyValues = (0 == allGoalsFuzzyValues ) ? oneGoalFuzzyValue : Expression.tConorm( allGoalsFuzzyValues, oneGoalFuzzyValue ); } } else { double oneGoalFuzzyValue = aSub.getFuzzyValue(); allGoalsFuzzyValues = (0 == allGoalsFuzzyValues ) ? oneGoalFuzzyValue : Expression.tConorm( allGoalsFuzzyValues, oneGoalFuzzyValue ); } } } } double fuzzyValue = allGoalsFuzzyValues / allGoalValues; return fuzzyValue; } private double evaluateOneGoal( Atom role, GameState state, GameStateScope scope, double terminalFuzzyValue, Predicate aGoal, int value) throws InterruptedException { boolean reached = state.isRoleGoalValue( role ) && state.getRoleGoalValue( role ) == value ; double gv_z = 0.0; if (timerFlag.interrupted()) throw Const.interrupt; mixin.preStateEvaluation(state, game, timerFlag); FuzzyResolution resolution = aGoal.fuzzyEvaluate( empty, scope, guard, timerFlag); gv_z = resolution.getFuzzyValue(); if (reached) { return Expression.tConorm( gv_z, terminalFuzzyValue ); } return Expression.tNorm( gv_z, terminalFuzzyValue ); } } /*package de.tu_dresden.inf.ggp06_2.strategies; import java.util.HashMap; import java.util.ArrayList; import java.util.List; import static java.util.Collections.sort; import org.apache.log4j.Logger; import de.tu_dresden.inf.ggp06_2.resolver.Predicate; import de.tu_dresden.inf.ggp06_2.resolver.Const; import de.tu_dresden.inf.ggp06_2.resolver.Expression; import de.tu_dresden.inf.ggp06_2.resolver.ExpressionList; import de.tu_dresden.inf.ggp06_2.resolver.structures.GameNode; import de.tu_dresden.inf.ggp06_2.resolver.structures.GameState; import de.tu_dresden.inf.ggp06_2.simulator.Game; import de.tu_dresden.inf.ggp06_2.simulator.flags.TimerFlag; public class TurnTakingSearch extends AbstractStrategy{ private static final Logger logger = Logger.getLogger(Novelty.class); private HashMap<ExpressionList, Integer> historyHeuristic; private TimerFlag flag; private int depthTreshold = 8; private int iteratedDeepeningStep = 2; private int searchDepthCounter = 1; private HashMap<GameNode, Double> nodeValues; private int numberOfPlayers; private int ourTurn; private void calculateOurTurn(){ GameState state; int index; for (index = 0; index<this.game.getRoleNames().size(); index++) if( this.game.getRoleNames().get( index ).equals( this.role )) break; state = this.game.getInitialNode().getState(); for(ourTurn=0; ourTurn < numberOfPlayers; ourTurn++){ ExpressionList moves = this.game.getCombinedLegalMoves( state, flag ).get( 0 ); if(!(moves.get(index).equals( Const.aNoop ))) break; state = this.game.produceNextNode( new GameNode(state), moves).getState(); } } public TurnTakingSearch(Game game, String role){ super(game,role); numberOfPlayers = this.game.getRoleNames().size(); calculateOurTurn(); historyHeuristic = new HashMap<ExpressionList, Integer>(); flag = new TimerFlag(); } private Double evaluatePossition(GameNode node){ *//** * TODO: call a propper method *//* if(node.getState().isTerminal()) return 1.0; return 0.0; } private Double doTheSearchIteration(GameNode node, int depth, Double alpha, Double beta){ HashMap<ExpressionList, Integer> rating = new HashMap<ExpressionList, Integer>(); //node.setVisited( node.getVisited()+1 ); *//** * use transposition tables *//* for (GameNode sameState : this.game.stateTree.gsHash2Nodes.get( node.getState() )){ if((sameState.getVisited() > node.getVisited()) && ((sameState.depth % this.game.getRoleNames().size()) == (sameState.depth % this.game.getRoleNames().size())) ){ nodeValues.put( node, nodeValues.get( sameState ) ); return nodeValues.get( sameState ); } } Double score = evaluatePossition(node); if(node.getState().isTerminal()){ node.setVisited( node.depth - depth ); nodeValues.put( node, score ); return score; } if(node.depth == depth){ node.setVisited( node.depth - depth ); nodeValues.put( node, score ); return score; } List<ExpressionList> moves = this.game.getCombinedLegalMoves( node.getState(), this.flag); if(moves.isEmpty()){ node.getState().setTerminal(); nodeValues.put( node, score ); return score; } for(ExpressionList key : moves){ if (historyHeuristic.containsKey( key )){ rating.put( key, historyHeuristic.get( key ) ); } else{ historyHeuristic.put( key, 0 ); rating.put( key, 0); } } *//** * TODO: Sort the moves *//* ArrayList<ExpressionList> movesList = new ArrayList<ExpressionList>(); ArrayList<Integer> movesValues = new ArrayList<Integer>(rating.values()); sort(movesValues); for(Integer val : movesValues){ for (ExpressionList key : rating.keySet()){ if((val == rating.get( key )) && (!movesList.contains( key ))){ movesList.add( key ); } } } int i = 3; Double result = 0.0; score = -1000.0; boolean computed = false; ExpressionList bestMove = new ExpressionList(new Predicate(Const.aDoes, Const.aNoop)); for(ExpressionList key : movesList){ for(GameNode child : this.game.stateTree.getChildren( node )) if (child.moves.contains( key )){ if ((node.depth % numberOfPlayers == ourTurn) || (node.depth % numberOfPlayers == ourTurn-1)){ if (node.depth < depthTreshold){ result = -doTheSearchIteration(child, depth, -beta, -alpha); }else result = -doTheSearchIteration(child, depth + i*iteratedDeepeningStep, -beta, -alpha); }else{ if (node.depth < depthTreshold){ result = doTheSearchIteration(child, depth, alpha, beta); }else result = doTheSearchIteration(child, depth + i*iteratedDeepeningStep, alpha, beta); } computed = true; break; } if(!computed){ GameNode newNode = this.game.produceNextNode( node, new ExpressionList(movesList.get( 0 )) ); newNode = this.game.stateTree.addChild( newNode.getState(), node, new ExpressionList(moves.get( 0 )) ); if ((node.depth % numberOfPlayers == ourTurn) || (node.depth % numberOfPlayers == ourTurn-1)){ if (node.depth < depthTreshold){ result = -doTheSearchIteration(newNode, depth, -beta, -alpha); }else result = -doTheSearchIteration(newNode, depth + i*iteratedDeepeningStep, -beta, -alpha); }else{ if (node.depth < depthTreshold){ result = doTheSearchIteration(newNode, depth, alpha, beta); }else result = doTheSearchIteration(newNode, depth + i*iteratedDeepeningStep, alpha, beta); } } i = (i>0)? i-1: 0; if (result > score) score = result; if (score >= beta){ bestMove = key; break; } alpha = (alpha > score)? alpha : score; } int value = historyHeuristic.get( bestMove ); value += Math.round(Math.pow(2, node.depth)); historyHeuristic.put( bestMove, value ); node.setVisited( node.depth - depth ); nodeValues.put( node, score ); return score; } private Double doTheSearch(GameNode node){ while(!flag.interrupted()){ doTheSearchIteration(node, searchDepthCounter*iteratedDeepeningStep, -1000.0, 1000.0); searchDepthCounter++; } return nodeValues.get( node ); } public Expression pickMove(GameNode node){ if(this.game.stateTree.getRoot() == null){ node = this.game.stateTree.addRootState( node.getState() ); } Double bestNodeValue = doTheSearch(node); for (GameNode child : this.game.stateTree.getChildren( node )){ if(this.nodeValues.get( child ) == bestNodeValue) return child.moves.get( 0 ); } return new Predicate(Const.aDoes, Const.aNoop); } } */