/*
*
*
*
*
*/
package com.hearthattack;
import com.hearthsim.exception.HSException;
import com.hearthsim.exception.HSInvalidCardException;
import com.hearthsim.exception.HSInvalidParamFileException;
import com.hearthsim.exception.HSParamNotFoundException;
import com.hearthsim.player.playercontroller.WeightedScorer;
import com.hearthsim.util.factory.BoardStateFactoryBase;
import com.hearthsim.util.factory.DepthBoardStateFactory;
import com.hearthsim.util.HearthActionBoardPair;
import com.hearthsim.util.tree.HearthTreeNode;
import com.hearthsim.util.tree.StopNode;
import com.hearthsim.model.BoardModel;
import com.hearthsim.model.PlayerModel;
import com.hearthsim.util.CardFactory;
import com.hearthsim.card.minion.Minion;
import com.hearthsim.card.Deck;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class moveGen {
private final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(this.getClass());
private final static int MAX_THINK_TIME = 20000;
private int numMoves = 10;
private WeightedScorer scorer = new WeightedScorer();
public moveGen() {
this(10);
}
public moveGen(int x){
numMoves = x;
this.scorer.setMyAttackWeight(0.9);
this.scorer.setMyHealthWeight(0.9);
this.scorer.setEnemyAttackWeight(1.0);
this.scorer.setEnemyHealthWeight(1.0);
this.scorer.setTauntWeight(1.0);
this.scorer.setMyHeroHealthWeight(0.1);
this.scorer.setEnemyHeroHealthWeight(0.1);
this.scorer.setManaWeight(0.1);
this.scorer.setMyNumMinionsWeight(0.5);
this.scorer.setEnemyNumMinionsWeight(0.5);
this.scorer.setSpellDamageAddWeight(0.0);
this.scorer.setSpellDamageMultiplierWeight(0.5);
this.scorer.setMyDivineShieldWeight(0.0);
this.scorer.setEnemyDivineShieldWeight(0.0);
this.scorer.setMyWeaponWeight(0.5);
this.scorer.setEnemyWeaponWeight(0.5);
}
public moveGen(int x, WeightedScorer y){
this.scorer = y;
numMoves = x;
}
public int getNumMoves() {
return numMoves;
}
public void setNumMoves(int x) {
numMoves = x;
}
//Pre : Takes a turn number and a BoardModel, just as a normal HearthSim AI would.
//Post: Returns a list of selected moves sorted in decreasing order
// of value with the end of the move occurring in the 0th position of the list.
public List<ArrayList<HearthActionBoardPair>> getMoves(int turn, BoardModel board) throws HSException{
PlayerModel playerModel0 = board.getCurrentPlayer();
PlayerModel playerModel1 = board.getWaitingPlayer();
BoardStateFactoryBase factory = new DepthBoardStateFactory(playerModel0.getDeck(), playerModel1.getDeck(), MAX_THINK_TIME, true);
HearthTreeNode toRet = new HearthTreeNode(board);
HearthTreeNode rootNode = factory.doMoves(toRet, this.scorer);
ArrayList<ArrayList<HearthActionBoardPair>> retList = new ArrayList<>();
ArrayList<HearthTreeNode> sortedChildArray = new ArrayList<>();
sortedChildArray = findChildren(rootNode);
int i = 0;
for( HearthTreeNode endState : sortedChildArray) {
if( i == numMoves) {
break;
}
HearthTreeNode current = endState;
retList.add(new ArrayList<HearthActionBoardPair>());
while(current.getParent() != null) {
if(current.getAction() == null) {
System.out.println("i= " + i);
System.out.print(current.getDepth());
}
retList.get(i).add(new HearthActionBoardPair(current.getAction(), current.data_.deepCopy()));
current = current.getParent();
}
retList.get(i).add(new HearthActionBoardPair(current.getAction(), current.data_.deepCopy()));
i++;
}
return retList;
}
//Pre : Takes a HearthTreeNode parent as the root of a tree.
//Post: returns a list of leaf nodes of the tree sorted by the value of
// getScore() such that the highest value is in the 0th position.
//Desc: Recursively calls itself on each child node. If the parent is a leaf,
// returns an ArrayList containing just the parent node. Otherwise, takes
// the ArrayList returned from its child nodes and sorts them according to value.
private ArrayList<HearthTreeNode> findChildren(HearthTreeNode parent) {
ArrayList<HearthTreeNode> ret = new ArrayList<>();
if(parent.getChildren() == null) {
ret.add(parent);
} else {
ArrayList<HearthTreeNode> x = new ArrayList<>();
ArrayList<HearthTreeNode> temp = new ArrayList<>();
for(HearthTreeNode child : parent.getChildren()){
x = findChildren(child);
int i = 0;
int j = 0;
//sorts moves by quality
while(i < ret.size() && j < x.size() && temp.size() < numMoves) {
if(ret.get(i).getScore() > x.get(j).getScore()) {
temp.add(ret.get(i));
i++;
} else {
temp.add(x.get(j));
j++;
}
}
//fills any remaining space in moveset
if((i < ret.size() || j < x.size()) && temp.size() < numMoves) {
if(i < ret.size()) {
while( i < ret.size() && temp.size() < numMoves){
temp.add(ret.get(i));
i++;
}
} else {
while( j < x.size() && temp.size() < numMoves) {
temp.add(x.get(j));
j++;
}
}
}
ret = temp;
temp = x;
temp.clear();
}
}
return ret;
}
}