Program: 112820
Project: 112820
Buggy source:
/** 
 * Recursively generate all possible moves This function recursively generates all possible moves that can be done starting from a given BoardState. While generating the moves, it applies the scoring function to each BoardState generated, and it will only keep the highest scoring branch. The results are stored in a tree structure and returned as a tree of BoardState class.
 * @param boardStateNode The initial BoardState wrapped in a HearthTreeNode.
 * @param scoreFunc The scoring function for AI.
 * @return boardStateNode manipulated such that all subsequent actions are children of the original boardStateNode input.
 */
public HearthTreeNode doMoves(HearthTreeNode boardStateNode,StateFunction<BoardState> scoreFunc) throws HSException {
  if (lethal_) {
    return null;
  }
  if (timedOut_) {
    return null;
  }
  if (System.currentTimeMillis() - startTime_ > maxTime_) {
    timedOut_=true;
    return null;
  }
  if (boardStateNode.numChildren() > 0) {
    for (    HearthTreeNode child : boardStateNode.getChildren()) {
      this.doMoves(child,scoreFunc);
    }
    return boardStateNode;
  }
  boolean lethalFound=false;
  if ((!boardStateNode.data_.isAlive_p0()) || (!boardStateNode.data_.isAlive_p1())) {
    if (!boardStateNode.data_.isAlive_p1()) {
      lethal_=true;
      lethalFound=true;
    }
  }
  if (!lethalFound) {
    boolean heroAbilityUsable=false;
    if (!boardStateNode.data_.getHero_p0().hasBeenUsed()) {
      for (int i=0; i <= boardStateNode.data_.getNumMinions_p0(); ++i) {
        HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
        newState=newState.data_.getHero_p0().useHeroAbility(0,0,i,newState,deck_);
        if (newState != null) {
          if (newState instanceof StopNode) {
          }
 else {
            newState=this.doMoves(newState,scoreFunc);
            if (newState != null)             boardStateNode.addChild(newState);
            heroAbilityUsable=true;
          }
        }
      }
      for (int i=0; i <= boardStateNode.data_.getNumMinions_p1(); ++i) {
        HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
        newState=newState.data_.getHero_p0().useHeroAbility(0,1,i,newState,deck_);
        if (newState != null) {
          if (newState instanceof StopNode) {
          }
 else {
            newState=this.doMoves(newState,scoreFunc);
            if (newState != null)             boardStateNode.addChild(newState);
            heroAbilityUsable=true;
          }
        }
      }
      if (heroAbilityUsable) {
        HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
        newState.data_.getHero_p0().hasBeenUsed(true);
        newState=this.doMoves(newState,scoreFunc);
        if (newState != null)         boardStateNode.addChild(newState);
      }
    }
    boolean allUsed=true;
    for (    final Card card : boardStateNode.data_.getCards_hand_p0()) {
      allUsed=allUsed && card.hasBeenUsed();
    }
    if (!allUsed) {
      HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
      for (      Card card : newState.data_.getCards_hand_p0()) {
        card.hasBeenUsed(true);
      }
      newState=this.doMoves(newState,scoreFunc);
      if (newState != null)       boardStateNode.addChild(newState);
    }
    int mana=boardStateNode.data_.getMana_p0();
    for (int ic=0; ic < boardStateNode.data_.getNumCards_hand(); ++ic) {
      if (boardStateNode.data_.getCard_hand_p0(ic).getMana() <= mana && !boardStateNode.data_.getCard_hand_p0(ic).hasBeenUsed()) {
        for (int i=0; i <= boardStateNode.data_.getNumMinions_p0() + 1; ++i) {
          HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
          Card card=newState.data_.getCard_hand_p0(ic);
          newState=card.useOn(ic,0,i,newState,deck_);
          if (newState != null) {
            if (newState instanceof StopNode) {
            }
 else {
              newState=this.doMoves(newState,scoreFunc);
              if (newState != null)               boardStateNode.addChild(newState);
            }
          }
        }
        for (int i=0; i <= boardStateNode.data_.getNumMinions_p1() + 1; ++i) {
          HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
          Card card=newState.data_.getCard_hand_p0(ic);
          newState=card.useOn(ic,1,i,newState,deck_);
          if (newState != null) {
            if (newState instanceof StopNode) {
            }
 else {
              newState=this.doMoves(newState,scoreFunc);
              if (newState != null)               boardStateNode.addChild(newState);
            }
          }
        }
      }
    }
    boolean allAttacked=true;
    for (    final Minion minion : boardStateNode.data_.getMinions_p0()) {
      allAttacked=allAttacked && minion.hasAttacked();
    }
    if (!allAttacked) {
      HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
      for (      Minion minion : newState.data_.getMinions_p0()) {
        minion.hasAttacked(true);
      }
      newState=this.doMoves(newState,scoreFunc);
      if (newState != null)       boardStateNode.addChild(newState);
    }
    for (int ic=1; ic < boardStateNode.data_.getNumMinions_p0() + 1; ++ic) {
      final Minion minion=boardStateNode.data_.getMinion_p0(ic - 1);
      if (minion.hasAttacked()) {
        continue;
      }
      ArrayList<Integer> attackable=boardStateNode.data_.getAttackableMinions_p1();
      for (      final Integer integer : attackable) {
        int i=integer.intValue();
        HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
        Minion tempMinion=newState.data_.getMinion_p0(ic - 1);
        newState=tempMinion.attack(ic,1,i,newState,deck_);
        if (newState != null) {
          if (newState instanceof StopNode) {
          }
 else {
            newState=this.doMoves(newState,scoreFunc);
            if (newState != null)             boardStateNode.addChild(newState);
          }
        }
      }
    }
  }
  if (boardStateNode.isLeaf()) {
    boardStateNode.setScore(scoreFunc.apply(boardStateNode.data_));
    boardStateNode.setNumNodesTries(1);
  }
 else {
    double tmpScore=-1.e300;
    int tmpNumNodesTried=0;
    Iterator<HearthTreeNode> iter=boardStateNode.getChildren().iterator();
    while (iter.hasNext()) {
      HearthTreeNode child=iter.next();
      tmpNumNodesTried+=child.getNumNodesTried();
      if (child.getScore() > tmpScore) {
        tmpScore=child.getScore();
      }
 else {
        iter.remove();
      }
    }
    boardStateNode.setScore(tmpScore);
    boardStateNode.setNumNodesTries(tmpNumNodesTried);
  }
  return boardStateNode;
}

Fixed version (ground truth):
/** 
 * Recursively generate all possible moves This function recursively generates all possible moves that can be done starting from a given BoardState. While generating the moves, it applies the scoring function to each BoardState generated, and it will only keep the highest scoring branch. The results are stored in a tree structure and returned as a tree of BoardState class.
 * @param boardStateNode The initial BoardState wrapped in a HearthTreeNode.
 * @param scoreFunc The scoring function for AI.
 * @return boardStateNode manipulated such that all subsequent actions are children of the original boardStateNode input.
 */
public HearthTreeNode doMoves(HearthTreeNode boardStateNode,StateFunction<BoardState> scoreFunc) throws HSException {
  if (lethal_) {
    return null;
  }
  if (timedOut_) {
    return null;
  }
  if (System.currentTimeMillis() - startTime_ > maxTime_) {
    timedOut_=true;
    return null;
  }
  if (boardStateNode.numChildren() > 0) {
    for (    HearthTreeNode child : boardStateNode.getChildren()) {
      this.doMoves(child,scoreFunc);
    }
    return boardStateNode;
  }
  boolean lethalFound=false;
  if ((!boardStateNode.data_.isAlive_p0()) || (!boardStateNode.data_.isAlive_p1())) {
    if (!boardStateNode.data_.isAlive_p1()) {
      lethal_=true;
      lethalFound=true;
    }
  }
  if (!lethalFound) {
    boolean heroAbilityUsable=false;
    if (!boardStateNode.data_.getHero_p0().hasBeenUsed()) {
      for (int i=0; i <= boardStateNode.data_.getNumMinions_p0(); ++i) {
        HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
        newState=newState.data_.getHero_p0().useHeroAbility(0,0,i,newState,deck_);
        if (newState != null) {
          if (newState instanceof StopNode) {
          }
 else {
            newState=this.doMoves(newState,scoreFunc);
            if (newState != null)             boardStateNode.addChild(newState);
            heroAbilityUsable=true;
          }
        }
      }
      for (int i=0; i <= boardStateNode.data_.getNumMinions_p1(); ++i) {
        HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
        newState=newState.data_.getHero_p0().useHeroAbility(0,1,i,newState,deck_);
        if (newState != null) {
          if (newState instanceof StopNode) {
          }
 else {
            newState=this.doMoves(newState,scoreFunc);
            if (newState != null)             boardStateNode.addChild(newState);
            heroAbilityUsable=true;
          }
        }
      }
      if (heroAbilityUsable) {
        HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
        newState.data_.getHero_p0().hasBeenUsed(true);
        newState=this.doMoves(newState,scoreFunc);
        if (newState != null)         boardStateNode.addChild(newState);
      }
    }
    boolean allUsed=true;
    for (    final Card card : boardStateNode.data_.getCards_hand_p0()) {
      allUsed=allUsed && card.hasBeenUsed();
    }
    if (!allUsed) {
      HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
      for (      Card card : newState.data_.getCards_hand_p0()) {
        card.hasBeenUsed(true);
      }
      newState=this.doMoves(newState,scoreFunc);
      if (newState != null)       boardStateNode.addChild(newState);
    }
    int mana=boardStateNode.data_.getMana_p0();
    for (int ic=0; ic < boardStateNode.data_.getNumCards_hand(); ++ic) {
      if (boardStateNode.data_.getCard_hand_p0(ic).getMana() <= mana && !boardStateNode.data_.getCard_hand_p0(ic).hasBeenUsed()) {
        for (int i=0; i <= boardStateNode.data_.getNumMinions_p0() + 1; ++i) {
          HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
          Card card=newState.data_.getCard_hand_p0(ic);
          newState=card.useOn(ic,0,i,newState,deck_);
          if (newState != null) {
            if (newState instanceof StopNode) {
            }
 else {
              newState=this.doMoves(newState,scoreFunc);
              if (newState != null)               boardStateNode.addChild(newState);
            }
          }
        }
        for (int i=0; i <= boardStateNode.data_.getNumMinions_p1() + 1; ++i) {
          HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
          Card card=newState.data_.getCard_hand_p0(ic);
          newState=card.useOn(ic,1,i,newState,deck_);
          if (newState != null) {
            if (newState instanceof StopNode) {
            }
 else {
              newState=this.doMoves(newState,scoreFunc);
              if (newState != null)               boardStateNode.addChild(newState);
            }
          }
        }
      }
    }
    boolean allAttacked=true;
    for (    final Minion minion : boardStateNode.data_.getMinions_p0()) {
      allAttacked=allAttacked && minion.hasAttacked();
    }
    if (!allAttacked) {
      HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
      for (      Minion minion : newState.data_.getMinions_p0()) {
        minion.hasAttacked(true);
      }
      newState=this.doMoves(newState,scoreFunc);
      if (newState != null)       boardStateNode.addChild(newState);
    }
    for (int ic=1; ic < boardStateNode.data_.getNumMinions_p0() + 1; ++ic) {
      final Minion minion=boardStateNode.data_.getMinion_p0(ic - 1);
      if (minion.hasAttacked()) {
        continue;
      }
      ArrayList<Integer> attackable=boardStateNode.data_.getAttackableMinions_p1();
      for (      final Integer integer : attackable) {
        int i=integer.intValue();
        HearthTreeNode newState=new HearthTreeNode((BoardState)boardStateNode.data_.deepCopy());
        Minion tempMinion=newState.data_.getMinion_p0(ic - 1);
        newState=tempMinion.attack(ic,1,i,newState,deck_);
        if (newState != null) {
          if (newState instanceof StopNode) {
          }
 else {
            newState=this.doMoves(newState,scoreFunc);
            if (newState != null)             boardStateNode.addChild(newState);
          }
        }
      }
    }
  }
  if (boardStateNode.isLeaf()) {
    boardStateNode.setScore(scoreFunc.apply(boardStateNode.data_));
    boardStateNode.setNumNodesTries(1);
  }
 else {
    double tmpScore=-1.e300;
    int tmpNumNodesTried=0;
    Iterator<HearthTreeNode> iter=boardStateNode.getChildren().iterator();
    HearthTreeNode bestBranch=null;
    while (iter.hasNext()) {
      HearthTreeNode child=iter.next();
      tmpNumNodesTried+=child.getNumNodesTried();
      if (child.getScore() > tmpScore) {
        tmpScore=child.getScore();
        bestBranch=child;
      }
    }
    boardStateNode.clearChildren();
    boardStateNode.addChild(bestBranch);
    boardStateNode.setScore(tmpScore);
    boardStateNode.setNumNodesTries(tmpNumNodesTried);
  }
  return boardStateNode;
}