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.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 SimultaneousSearch extends AbstractStrategy {
private TimerFlag flag;
private int depthTreshold = 6;
private Map<ExpressionList, Long> historyHeuristic;
private int initialDepth = 1;
private int availableBoosts = 5;
private int ourRoleIndex;
public SimultaneousSearch(Game game, String role){
super(game,role);
historyHeuristic = new HashMap<ExpressionList, Long>();
flag = new TimerFlag();
ourRoleIndex = 0;
for(Atom a : this.game.getRoleNames()){
if(a.equals( this.role )) break;
ourRoleIndex++;
}
}
public SimultaneousSearch(Game game, String role, TimerFlag flag){
this(game, role);
this.timerFlag = flag;
}
@Override
public Expression pickMove(GameNode node){
return doTheSearch( node );
}
private Expression doTheSearch(GameNode node) {
Expression bestDirectMove;
try{
bestDirectMove = this.game.getLegalMoves( role, node.getState(), timerFlag ).get( 0 );
} catch (InterruptedException ex) {
return new Predicate(Const.aDoes, role, Const.aNoop);
}
int incr = 1;
double nodeValue =0.0;
while ( !(nodeValue == 1.0) && (incr < 11)){
try{
nodeValue = doSearchIteration(node, incr*initialDepth);
//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( ourRoleIndex );
break;
}
}
} catch (InterruptedException ex) {
return bestDirectMove;
}
incr++;
}
for(GameNode aNode : this.game.stateTree.getChildren( node )){
if(aNode.getNodeValue() == node.getNodeValue()){
bestDirectMove = aNode.getMoves().get( ourRoleIndex );
break;
}
}
return bestDirectMove;
}
private double doSearchIteration(
GameNode node, int depth)
throws InterruptedException {
//logger.info( node );
double value = 0.0;
if (node.getNodeValue() == 1.0) return 1.0;
if(node.getNodeValue() == 1.0) return 1.0;
if (node.getState().isTerminal()){
//logger.info( " terminal case " );
value = heurisicValue(node, this.role);
storeNodeValue(node, depth, value);
} else if (wasPriorVisited(node)) {
value = priorValue(node);
} else if (0 == depth){
//logger.info( " 0==depth case " );
value = heurisicValue(node, this.role);
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 );
if (depth == initialDepth) {
//logger.info( " expansion case for : "+depth+" value "+value );
}
storeNodeValue(node, depth, value);
}
//logger.info( node );
return value;
}
private double priorValue(GameNode node) {
List<GameNode> nodes = game.stateTree.gsHash2Nodes.get( node.getState().hashCode() );
for (GameNode aNode : nodes){
int previousSearchDepth = aNode.getSearchDepth();
if (previousSearchDepth > node.getSearchDepth())
return aNode.getNodeValue();
}
return node.getNodeValue();
}
private void storeNodeValue(GameNode node, int depth, double value) {
node.setSearchDepth( depth );
node.setNodeValue( value );
}
private boolean wasPriorVisited(GameNode node) {
List<GameNode> nodes = game.stateTree.gsHash2Nodes.get( node.getState().hashCode() );
for (GameNode aNode : nodes){
int previousSearchDepth = aNode.getSearchDepth();
if (previousSearchDepth > node.getSearchDepth())
return true;
}
return false;
}
private double processAvailableMoves(
GameNode node, int depth,
Set<ExpressionList> moves, List<ExpressionList> legalMoves)
throws InterruptedException {
double currentBest = -1;
ExpressionList currentBestMove = legalMoves.get( 0 );
int childOrder = moves.size();
HashMap<ExpressionList, Double>childrenValues = new HashMap<ExpressionList, Double>();
while( ! moves.isEmpty()){
ExpressionList aMove = extractMoveAccordingToHH(moves);
GameNode nextNode = this.game.produceNextNode( node, aMove, timerFlag );
boolean boostingPerformed = false;
if ( depth == 1 &&
node.getDepth() > this.depthTreshold &&
availableBoosts > 0){
depth = childOrder*initialDepth;
availableBoosts--;
boostingPerformed = true;
//logger.info(" boosting! ");
}
childrenValues.put( aMove, doSearchIteration( nextNode, depth-1 ));
//logger.info( "tmpValue: "+tmpValue );
if ( boostingPerformed ){
availableBoosts++;
}
currentBest = chooseBestMove(childrenValues);
if (1.0 == currentBest){
break;
}
childOrder--;
}
node.getState().setFuzzyValueForRole( role, currentBest );
updateHistoryHeuristic(currentBestMove, depth*availableBoosts);
return currentBest;
}
private double chooseBestMove(HashMap<ExpressionList, Double> childrenValues) {
HashMap<Expression, Double> maximizeMe = new HashMap<Expression, Double>();
double bestValue = -1000.0;
Set<ExpressionList> keySet = childrenValues.keySet();
for (ExpressionList ourMoves : keySet){
if(maximizeMe.containsKey( ourMoves.get( ourRoleIndex ) )){
if(maximizeMe.get( ourMoves.get( ourRoleIndex ) ) > childrenValues.get( ourMoves ))
maximizeMe.put( ourMoves.get( ourRoleIndex ), childrenValues.get( ourMoves ) );
} else
maximizeMe.put( ourMoves.get( ourRoleIndex ), childrenValues.get( ourMoves ) );
}
Set<Expression> keySet2 = maximizeMe.keySet();
for (Expression aMove: keySet2)
if ( maximizeMe.containsKey(aMove) &&
maximizeMe.get(aMove) > bestValue )
bestValue = maximizeMe.get(aMove);
return bestValue;
}
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, Atom player) {
GameState state = node.getState();
//if ( state.isTerminal()){
if ( state.isRoleGoalValue( player )){
if (state.isTerminal()){
//logger.info( " GOT treminal! "+state );
return state.getRoleGoalValue( player )/100.0;
}
// if (intermediateStateValues.containsKey(state)) {
// return intermediateStateValues.get( state );
// }
double d = (state.getRoleGoalValue( player ) - 1.0)/100.0;
//logger.info( " GOAL state! "+state+d );
return d;
}
return 0.0;
}
}